Merge pull request #1 from cheveguerra/NoInitial

Combiar con No initial
This commit is contained in:
2023-02-07 03:27:44 -06:00
committed by GitHub
15 changed files with 1623 additions and 296 deletions

2
.env
View File

@@ -1,6 +1,6 @@
######DATABASE: none, mysql, dialogflow ######DATABASE: none, mysql, dialogflow
DEFAULT_MESSAGE=true DEFAULT_MESSAGE=false
SAVE_MEDIA=true SAVE_MEDIA=true
PORT=3005 PORT=3005
DATABASE=none DATABASE=none

7
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}

57
Excel.js Normal file
View File

@@ -0,0 +1,57 @@
const ExcelJS = require('exceljs');
const fs = require('fs')
const workbook = new ExcelJS.Workbook();
const guardaXLSDatos = async (nombre, edad, sexo) => {
// read from a file
await workbook.xlsx.readFile('./bot.xlsx');
// fetch sheet by name
const worksheet = workbook.getWorksheet('Bot');
const rowValues = [];
rowValues[1] = nombre;
rowValues[2] = edad;
rowValues[3] = sexo;
worksheet.addRow(rowValues);
await workbook.xlsx.writeFile('./bot.xlsx');
console.log(rowValues)
console.log("Guardamos XLS")
}
const leeXLSDatos = async (srchStr) => {
// read from a file
await workbook.xlsx.readFile('./bot.xlsx');
// fetch sheet by name
const worksheet = workbook.getWorksheet('Bot');
console.log(worksheet.rowCount)
let colNombre = worksheet.getColumn(1).values
let cont = 0
let encontrado = 0
let row
let res = []
// while (cont <= worksheet.rowCount && encontrado == 0) { // Ocupamos while en lugar de forEach para que deje de buscar en cuanto encuentre el resultado.
// console.log(cont, colNombre[cont], srchStr)
// if(colNombre[cont] === srchStr) {
// row = worksheet.getRow(cont);
// res['nombre'] = row.getCell(1).value
// res['edad'] = row.getCell(2).value
// res['sexo'] = row.getCell(3).value
// encontrado = colNombre[cont]
// }
// cont++;
// }
// console.log("RES=", res)
// for (let index = 0; index < worksheet.rowCount; index++) {
// }
let rows = []
worksheet.eachRow(function(row, rowNumber) {
// console.log('Row ' + rowNumber + ' = ' + JSON.stringify(row.values));
rows[rowNumber-1]={'nombre':row.getCell(1).value, 'carnet':row.getCell(4).value, 'factura':row.getCell(5).value, 'prefijo':row.getCell(6).value}
});
// console.log(rows)
return rows
}
module.exports = {guardaXLSDatos, leeXLSDatos};

View File

@@ -1,5 +1,5 @@
## Chatbot Whatsapp (OpenSource) ## Chatbot Whatsapp (OpenSource)
#### Actualizado Diciembre 2022 #### Actualizado Febrero 2023
Este proyecto es un clon de la **version 1** (legacy) de [Leifer Mendez](https://github.com/leifermendez/bot-whatsapp) y tiene las siguientes modificaciones: Este proyecto es un clon de la **version 1** (legacy) de [Leifer Mendez](https://github.com/leifermendez/bot-whatsapp) y tiene las siguientes modificaciones:
@@ -33,7 +33,7 @@ Este proyecto es un clon de la **version 1** (legacy) de [Leifer Mendez](https:/
"pasoRequerido":"menu" "pasoRequerido":"menu"
} }
``` ```
- Permite **expresiones regulares** en las palabras predefinidas en el initial.json. - Permite **expresiones regulares** en las palabras predefinidas en el **initial.json**.
- Si queremos usar RegExp, en los "keywords" de **inital.json**, en lugar de un arreglo, debemos usar un string ( quitamos los [] ) - Si queremos usar RegExp, en los "keywords" de **inital.json**, en lugar de un arreglo, debemos usar un string ( quitamos los [] )
y en él usamos "*" para significar cualquier texto y "|" para significar "OR", esto nos permite ser mas flexibles y en él usamos "*" para significar cualquier texto y "|" para significar "OR", esto nos permite ser mas flexibles
con los "keywords", por ejemplo, si queremos que el mensaje pueda decir: con los "keywords", por ejemplo, si queremos que el mensaje pueda decir:
@@ -62,7 +62,7 @@ Este proyecto es un clon de la **version 1** (legacy) de [Leifer Mendez](https:/
- Ponemos __%dia_semana%__ para que aparezca "lunes, martes, miercoles, etc" dependiendo del día de la semana. - Ponemos __%dia_semana%__ para que aparezca "lunes, martes, miercoles, etc" dependiendo del día de la semana.
- Ponemos __%msjant_XX%__ para que aparezca el mensaje xx anterior, es decir, si quieres mostrar el texto de 2 mensajes anteriores se pone %msjant_2%. - Ponemos __%msjant_XX%__ para que aparezca el mensaje xx anterior, es decir, si quieres mostrar el texto de 2 mensajes anteriores se pone %msjant_2%.
- etc, etc, se pueden agregar mas remplazos en la funcion "remplazos" en el archivo "adapter\index.js". - etc, etc, se pueden agregar mas remplazos en la funcion "remplazos" en el archivo "adapter\index.js".
- Permite el envío de **multiples mensajes** definidos en la **misma respuesta** del **response.json**. (Esta modificación se la robe por completo a [KJoaquin](https://github.com/KJoaquin), el lo solucionó [aquí](https://github.com/codigoencasa/bot-whatsapp/issues/111#issuecomment-1353504575) 🙌🏽 y yo solo lo adapté a mi repo!) - Permite el envío de **multiples mensajes** definidos en la **misma respuesta** del **response.json**. (Esta modificación se la robe por completo a [KJoaquin](https://github.com/KJoaquin), el lo solucionó [aquí](https://github.com/codigoencasa/bot-whatsapp/issues/111#issuecomment-1353504575) 🙌🏽 y yo solo lo adapté a mi repositorio!.)
Antes: Antes:
```json ```json
@@ -74,7 +74,7 @@ Este proyecto es un clon de la **version 1** (legacy) de [Leifer Mendez](https:/
} }
} }
``` ```
Ahora **replyMessage** debe de contener un arreglo con los mensajes que se van a enviar: Ahora "```replyMessage```" debe de contener un arreglo con los mensajes que se van a enviar:
```json ```json
{ {
"ejemploNuevo":{ "ejemploNuevo":{
@@ -88,9 +88,34 @@ Este proyecto es un clon de la **version 1** (legacy) de [Leifer Mendez](https:/
} }
} }
``` ```
- Permite conectarse a **APIs**, por ejemplo: Google Sheets, Excel y cualquier otra API que se pueda llamar desde una funcion, esto se hace agregando el parametro "```funcion```" al **response.json**.
```
"Desbloqueo":{
"keywords": "desbloqueo",
"replyMessage":[
"Mensaje de desbloqueo de usuarios."
],
"funcion":"getFakeHTTP", //esta linea ejecuta la funcion.
"media":null,
"trigger":null,
"pasoRequerido":"soporte"
}
```
- Los archivos **initial.json** y **response.json** se unificaron y ya solo se usa el **response.json**, para esto solo se agrega el parametro "```keywords```" del **initial.json** al **response.json**
- Se puede especificar que al terminar un paso, el flujo se **vaya automaticamente** a otro, por ejemplo, si tenemos un flujo de tres pasos, y queremos que al terminar el tercer paso se regrese automaticamente al primero, agregamos el parametro "```goto```" al **response.json** del tercer paso y ponemos el nombre del paso 1.
```
"paso3":{
"keywords": ["zapatos"],
"replyMessage":["Gracias por tu compra"],
"media":null,
"trigger":null,
"goto":"paso1"
},
```
- Las modificaciones están enfocadas al uso de los archivos __initial.json__ y __response.json__, yo no uso MySQL o DialogFlow, así que no sé si las modificaciones funcionen con esos modulos, en particular el __remplazo %msjant_XX%__ depende de los archivos __JSON__ que se crean en el directorio "chats". - Las modificaciones están enfocadas al uso de los archivos __initial.json__ y __response.json__, yo no uso MySQL o DialogFlow, así que no sé si las modificaciones funcionen con esos modulos, en particular el __remplazo %msjant_XX%__ depende de los archivos __JSON__ que se crean en el directorio "chats".
- Tiene agregado el parche de **botones y listas**, así que funcionan sin problema (las listas no funcionan si el bot esta ligado a un número que use **Whatsapp Business**). - Tiene agregado el parche de **botones y listas**, así que funcionan sin problema (las listas no funcionan si el bot esta **ligado** a un número que use **Whatsapp Business**).
- Tiene los ultimos parches de **DialogFlow** (27-dic-2022) (When Dialogflow asks for an Image, then **Upload it to Google Drive** and then generate Shared Link) - Tiene los ultimos parches de **DialogFlow** (27-dic-2022) (When Dialogflow asks for an Image, then **Upload it to Google Drive** and then generate Shared Link)
## INICIA DOCUMENTACION DEL PROYECTO ORIGINAL ## INICIA DOCUMENTACION DEL PROYECTO ORIGINAL
@@ -106,7 +131,7 @@ El siguiente proyecto se realizó con fines educativos para el canal de [Youtube
> [VER](https://github.com/leifermendez/bot-whatsapp/commits/main) > [VER](https://github.com/leifermendez/bot-whatsapp/commits/main)
### Busco colaboradores ⭐ ### Busco colaboradores ⭐
Hola amigos me gusta mucho este proyecto pero por cuestiones de tiempo se me dificulta mantener las actualizaciones si alguno quieres participar en el proyecto escribeme a leifer.contacto@gmail.com Hola amigos me gusta mucho este proyecto pero por cuestiones de tiempo se me dificulta mantener las actualizaciones si alguno quiere participar en el proyecto escribanme a leifer.contacto@gmail.com
#### Acceso rápido #### Acceso rápido
> Si tienes una cuenta en __heroku__ puedes desplegar este proyecto con (1 click) > Si tienes una cuenta en __heroku__ puedes desplegar este proyecto con (1 click)
@@ -237,7 +262,7 @@ __Listo 😎__
![](https://i.imgur.com/OSUgljQ.png) ![](https://i.imgur.com/OSUgljQ.png)
> Ahora deberías obtener un arespuesta por parte del BOT como la siguiente, ademas de esto tambien se crea un archivo excel > Ahora deberías obtener una respuesta por parte del BOT como la siguiente, ademas de esto tambien se crea un archivo excel
con el historial de conversación con el número de tu cliente con el historial de conversación con el número de tu cliente
![](https://i.imgur.com/lrMLgR8.png) ![](https://i.imgur.com/lrMLgR8.png)

View File

@@ -1,26 +1,40 @@
const { getData, getReply, saveMessageMysql } = require('./mysql') const { getData, getReply, saveMessageMysql } = require('./mysql')
const { saveMessageJson } = require('./jsonDb') const { saveMessageJson } = require('./jsonDb')
const { getDataIa } = require('./diaglogflow') const { getDataIa } = require('./diaglogflow')
const stepsInitial = require('../flow/initial.json') // const stepsInitial = require('../flow/initial.json')
const stepsReponse = require('../flow/response.json') const stepsReponse = require('../flow/response.json')
const { isUndefined } = require('util'); const { isUndefined } = require('util');
var msjsRecibidos = [];
var ultimoStep; //MOD by CHV - var ultimoStep; //MOD by CHV -
var pasoAnterior = []; //MOD by CHV - Para guardar el paso anterior de cada número.
var pasoRequerido; //MOD by CHV - var pasoRequerido; //MOD by CHV -
var vamosA = ""; //MOD by CHV - var _vamosA = ""; //MOD by CHV -
var VA = ""; //MOD by CHV - var VA = ""; //MOD by CHV -
var elNum; //MOD by CHV - var elNum; //MOD by CHV -
var cumplePasoPrevio; //MOD by CHV - var cumplePasoPrevio = []; //MOD by CHV -
const resps = require('../flow/response.json'); //MOD by CHV - Agregamos para traer las respuestas. const resps = require('../flow/response.json'); //MOD by CHV - Agregamos para traer las respuestas.
const { appendFile } = require('fs') const { appendFile } = require('fs')
/**
* Regresa un arreglo de objetos como el stepsInitial original, que se generaba desde "initial.json".
* Contiene el nombre del paso (key) y las palabras clave correspondientes (keywords).
*/
const getStepsInitial = () => {
let contSI = 0
let stepsInitial0 = []
for (const resp in stepsReponse) {
// console.log(`${resp}: ${stepsReponse[resp]['keywords']}`);
if(stepsReponse[resp]['keywords'] !== undefined){
stepsInitial0[contSI]= {"keywords":stepsReponse[resp]['keywords'], "key":resp}
contSI++
}
}
return stepsInitial0
}
const stepsInitial = getStepsInitial()
const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - Agregamos parametro "num" para recibir el número de "app.js" const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - Agregamos parametro "num" para recibir el número de "app.js"
// console.log(num) // console.log(num)
elNum = num //MOD by CHV - elNum = num //MOD by CHV -
if(siguientePaso.find(k => k.numero.includes(elNum))){ if(siguientePaso.find(k => k.numero.includes(elNum))){
console.log("siguientePaso="+siguientePaso.find(k => k.numero.includes(elNum))["numero"], siguientePaso.find(k => k.numero.includes(elNum))["va"]) console.log("siguientePaso="+siguientePaso.find(k => k.numero.includes(elNum))["numero"], siguientePaso.find(k => k.numero.includes(elNum))["va"])
// ultimoStep = siguientePaso.find(k => k.numero.includes(elNum))["va"]
pasoAnterior[elNum] = siguientePaso.find(k => k.numero.includes(elNum))["va"] //Asignamos pasoAnterior al número. pasoAnterior[elNum] = siguientePaso.find(k => k.numero.includes(elNum))["va"] //Asignamos pasoAnterior al número.
siguientePaso.splice(siguientePaso.indexOf(elNum), 1) siguientePaso.splice(siguientePaso.indexOf(elNum), 1)
console.log("******************** "+siguientePaso.find(k => k.numero.includes(elNum))) console.log("******************** "+siguientePaso.find(k => k.numero.includes(elNum)))
@@ -28,11 +42,43 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV -
if(siguientePaso.length>1){console.log(siguientePaso[1]["numero"], siguientePaso[1]["va"])} if(siguientePaso.length>1){console.log(siguientePaso[1]["numero"], siguientePaso[1]["va"])}
/** /**
* Si no estas usando un gesto de base de datos * Si no estas usando una base de datos
*/ */
if (process.env.DATABASE === 'none') { if (process.env.DATABASE === 'none') {
var { key } = stepsInitial.find(k => k.keywords.includes(message)) || { key: null } //******************************************************************************** */
var logKeysArray = false // Poner en verdadero para ver logs de esta seccion.
//******************************************************************************** */
key = null
let q = 0;
if(logKeysArray) console.log(stepsInitial.length)
while (key == null && q < stepsInitial.length) {
if(Array.isArray(stepsInitial[q].keywords)){
let r = 0
let rFound = false
while(!rFound && r<stepsInitial[q].keywords.length){
if(logKeysArray) console.log(q, "keyword=", stepsInitial[q].keywords[r], "msj=", message)
if(logKeysArray) console.log(q, "req=", resps[stepsInitial[q].key.toString()].pasoRequerido, "ant=", pasoAnterior[elNum])
if( message.toLowerCase() == stepsInitial[q].keywords[r].toLowerCase() && ( // Si el mensaje coincide con la palabra clave Y pasoRequerido es igual a pasoAnterior ...
resps[stepsInitial[q].key.toString()].pasoRequerido == undefined ||
resps[stepsInitial[q].key.toString()].pasoRequerido == pasoAnterior[elNum]
)
){
key = stepsInitial[q].key
if(logKeysArray) console.log(key, " SI COINCIDE")
rFound = true
}
else
{
// key = null
if(logKeysArray) console.log("No coincide")
}
r++
}
}
q++
}
if(logKeysArray) console.log("KEY = ", key)
// var { key } = stepsInitial.find(k => k.keywords.includes(message)) || { key: null }
/* ############################################### * REGEXP * #################################################### /* ############################################### * REGEXP * ####################################################
Si queremos usar RegExp, en los "keywords" de inital.json, en lugar de un arreglo usamos un string (quitamos los []) Si queremos usar RegExp, en los "keywords" de inital.json, en lugar de un arreglo usamos un string (quitamos los [])
@@ -52,42 +98,48 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV -
var {keywords} = stepsInitial.find(k => k.key.includes(key)) || { keywords: null } var {keywords} = stepsInitial.find(k => k.key.includes(key)) || { keywords: null }
if(!Array.isArray(keywords)){key=null;}//Si "keywords" no es arreglo entonces ponemos "key" en null y usamos REGEXP para buscar reglas. if(!Array.isArray(keywords)){key=null;}//Si "keywords" no es arreglo entonces ponemos "key" en null y usamos REGEXP para buscar reglas.
if(key == null && message.length > 0){ if(key == null && message.length > 0){
console.log("======= KEY ES NULO USAMOS REGEXP ======="); //******************************************************************************** */
for (i=0; i<stepsInitial.length;i++){ var logRegEx = false
// console.log(i, stepsInitial[i].keywords, message.match(stepsInitial[i].keywords.toString().replaceAll("*",".*"))); //******************************************************************************** */
if(!Array.isArray(stepsInitial[i].keywords)){// Si "Keywords" NO es arreglo entonces ... console.log("======= KEY ES NULO, USAMOS REGEXP =======");
x = null; for (si=0; si<stepsInitial.length;si++){
console.log("KEY=|" + stepsInitial[i].key.toString() + "|" ) if(!Array.isArray(stepsInitial[si].keywords)){// Si "Keywords" NO es arreglo entonces ...
// if(resps[stepsInitial[i].key.toString()].pasoRequerido != undefined){pr = resps[stepsInitial[i].key].pasoRequerido}; var coincideKeyword = null;
// console.log(resps[stepsInitial[i].key.toString()].pasoRequerido== ultimoStep) if(logRegEx) console.log("*** PASO=" + stepsInitial[si].key.toString() + " - REQUERIDO=" + resps[stepsInitial[si].key.toString()].pasoRequerido + " - ANTERIOR=" + pasoAnterior[elNum])
console.log("Esta Key=" + stepsInitial[i].key.toString() + " - pasoReq=" + resps[stepsInitial[i].key.toString()].pasoRequerido + " - PasoAnt=" + ultimoStep+"|"+pasoAnterior[elNum]) //Si NO hay paso requerido, o el paso requerido es IGUAL al paso anterior, entonces ...
if(resps[stepsInitial[i].key.toString()].pasoRequerido == undefined || resps[stepsInitial[i].key.toString()].pasoRequerido == pasoAnterior[elNum]){ if(resps[stepsInitial[si].key.toString()].pasoRequerido == undefined || resps[stepsInitial[si].key.toString()].pasoRequerido == pasoAnterior[elNum]){
var tempKeyword = ""; var tempKeyword = "";
if (stepsInitial[i].keywords == "%solo_correos%"){ if(logRegEx) console.log(" - El paso requerido COINCIDE con el anterior, o NO hay paso requerido.")
console.log("solo_correos") if (stepsInitial[si].keywords == "%solo_correos%"){
if(logRegEx) console.log("solo_correos")
tempKeyword = "[a-zA-Z0-9]+[_a-zA-Z0-9\.-]*[a-zA-Z0-9]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+[\.][a-zA-Z]{2,12})"} tempKeyword = "[a-zA-Z0-9]+[_a-zA-Z0-9\.-]*[a-zA-Z0-9]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+[\.][a-zA-Z]{2,12})"}
else{tempKeyword = stepsInitial[i].keywords.toString().replaceAll("*",".*")} else {
x = message.match(tempKeyword); tempKeyword = stepsInitial[si].keywords.toString().replaceAll("*",".*")
// console.log("Keywords="+stepsInitial[i].keywords + " - key=" + stepsInitial[i].key + " - pasoReq=" + resps[stepsInitial[i].key].pasoRequerido + " - PasoAnt=" + ultimoStep) }
// console.log("x:"+x+" - ultimoStep="+ultimoStep+" - pasoReq="+resps[stepsInitial[i].key].pasoRequerido); coincideKeyword = message.match(tempKeyword); // Verdadero cuando el mensaje COINCIDE con la palabre clave.
// console.log(resps[stepsInitial[i].key].replyMessage.toString()) if (coincideKeyword != null){ //Si el mensaje COINCIDE con la palabra clave.
if (x != null){ if(logRegEx) console.log(" - - El mensaje COINCIDE con el keyword")
key = stepsInitial[i].key; key = stepsInitial[si].key;
if(resps[stepsInitial[i].key].pasoRequerido != null && resps[stepsInitial[i].key].pasoRequerido != pasoAnterior[elNum]){key=null;} //Si HAY paso requerido, y el paso requerido es DIFERENTE del paso anterior, entonces ...
// console.log("KEY="+key+" - X="+x); if(resps[stepsInitial[si].key].pasoRequerido != null && resps[stepsInitial[si].key].pasoRequerido != pasoAnterior[elNum]){
if(resps[stepsInitial[i].key].replyMessage.toString().search("/URL") > -1){ key=null
console.log("**************** HAY URL ****************") if(logRegEx) console.log(" - - - Hay paso requerido y NO COINCIDE con en paso anterior")
}
if(resps[stepsInitial[si].key].replyMessage.toString().search("/URL") > -1){
if(logRegEx) console.log("**************** HAY URL ****************")
} }
break; break;
} }
else{x = null;} else {
} else coincideKeyword = null
{ console.log("NO CUMPLE PASO REQ"); }
console.log("pasoReq=" + resps[stepsInitial[i].key.toString()].pasoRequerido + " - PasoAnt=" + ultimoStep) }
else {
if(logRegEx) console.log("--- NO CUMPLE PASO REQ");
} }
} }
} }
// console.log("<<<<<<<<< "+key); // console.log("<<<<<<<<< " + key);
// cumplePasoRequerido(key) // cumplePasoRequerido(key)
// ultimoPaso = pasoRequerido; // ultimoPaso = pasoRequerido;
// ultimoStep = key; // ultimoStep = key;
@@ -96,19 +148,14 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV -
// if(key != null){remplazos(resps[key].replyMessage.join(''));} // if(key != null){remplazos(resps[key].replyMessage.join(''));}
if(resps[key]!=undefined){VA = resps[key].goto}else{VA=null} if(resps[key]!=undefined){VA = resps[key].goto}else{VA=null}
cumplePasoRequerido(key); cumplePasoRequerido(key);
vamosA = VA; _vamosA = VA;
// console.log(elNum) if(logRegEx) console.log("cumplePasoPrevio[elNum]=", cumplePasoPrevio[elNum], "_vamosA=", _vamosA)
if(_vamosA != "" && _vamosA != undefined && cumplePasoPrevio[elNum] == true){
if(vamosA != "" && vamosA != undefined && cumplePasoPrevio == true){ if(logRegEx) console.log("ASIGNAMOS _VAMOSA = " + _vamosA);
// console.log("ASIGNAMOS VAMOSA = " + vamosA); pasoAnterior[elNum] = _vamosA;
pasoAnterior[elNum] = vamosA;
} }
// console.log("ULTIMOSTEP="+ultimoStep) _vamosA = "";
vamosA = ""; if(cumplePasoPrevio[elNum]) {resolve(response);}
// console.log("MESSAGE: "+message);
// console.log("KEY: "+key);
// console.log("RESPONSE: "+response);
if(cumplePasoPrevio) {resolve(response);}
} }
/** /**
@@ -119,12 +166,11 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV -
resolve(dt) resolve(dt)
}); });
} }
}) })
const reply = (step) => new Promise((resolve, reject) => { const reply = (step) => new Promise((resolve, reject) => {
/** /**
* Si no estas usando un gesto de base de datos * Si no estas usando una base de datos
*/ */
if (process.env.DATABASE === 'none') { if (process.env.DATABASE === 'none') {
let resData = { replyMessage: '', media: null, trigger: null } let resData = { replyMessage: '', media: null, trigger: null }
@@ -176,7 +222,7 @@ const saveMessage = ( message, trigger, number, regla ) => new Promise( async (r
resolve( await saveMessageMysql( message, trigger, number ) ) resolve( await saveMessageMysql( message, trigger, number ) )
break; break;
case 'none': case 'none':
resolve( await saveMessageJson( message, trigger, number, regla) ) //MOD by CHV - Agregamos el paranetro "regla" resolve( await saveMessageJson( message, trigger, number, regla) ) //MOD by CHV - Agregamos el parametro "regla"
// console.log("REGLA DESDE APP.JS="+regla) // console.log("REGLA DESDE APP.JS="+regla)
break; break;
default: default:
@@ -185,13 +231,26 @@ const saveMessage = ( message, trigger, number, regla ) => new Promise( async (r
} }
}) })
module.exports = { get, reply, getIA, saveMessage, remplazos, stepsInitial } //MOD by CHV - Agregamos "remplazos" y "stepsInitial" para usarlos en "apps.js" module.exports = { get, reply, getIA, saveMessage, remplazos, stepsInitial, vamosA, traeUltimaVisita } //MOD by CHV - Agregamos "remplazos" y "stepsInitial" para usarlos en "apps.js"
/**
* Asigna el valor especificado a la variable pasoAnterior.
* Esta hace que el flujo se redirija al paso siguente al especificado.
* NO EJECUTA EL PASO DADO, solo espfecifica cual es el paso anterior para cuando una regla tiene el parametro "pasoRequerido".
* @param {elNum} string - El numero del remitente.
* @param {elPaso} string - El paso al que se va redirigir el flujo.
*/
function vamosA (elNum, elPaso){
pasoAnterior[elNum] = elPaso;
console.log("Asignamos pasoAnterior con " + elPaso, elNum)
}
/** /**
* Reemplaza texto en la respuesta con variables predefinidas. * Reemplaza texto en la respuesta con variables predefinidas.
*/ */
function remplazos(elTexto, extraInfo){ function remplazos(elTexto, extraInfo){
if(elTexto == null){elTexto = '';} if(elTexto == null){elTexto = '';}
const fs = require('fs');
laLista = elTexto.toString().split(' '); laLista = elTexto.toString().split(' ');
// console.log(laLista); // console.log(laLista);
// console.log('============= remplazos ============'); // console.log('============= remplazos ============');
@@ -258,28 +317,28 @@ function remplazos(elTexto, extraInfo){
} }
if(laLista[i].search('%msjant_')>-1){//Remplaza con el mensaje anterior especificado. if(laLista[i].search('%msjant_')>-1){//Remplaza con el mensaje anterior especificado.
var histlMsjs = {}; var histlMsjs = {};
console.log("entramos a msjant") // console.log("entramos a msjant")
// var hayHistorial = (chkFile(`${__dirname}/chats/`+from+".json")); // var hayHistorial = (chkFile(`${__dirname}/chats/`+from+".json"));
if(chkFile(`${__dirname}/../chats/`+elNum+".json")){ if(chkFile(`${__dirname}/../chats/`+elNum+".json")){
let rawdata = fs.readFileSync(`./chats/${elNum}.json`); let rawdata = fs.readFileSync(`./chats/${elNum}.json`);
let elHistorial0 = JSON.parse(rawdata); let elHistorial0 = JSON.parse(rawdata);
elHistorial = elHistorial0["messages"]; elHistorial = elHistorial0["messages"];
elHistorial = elHistorial.filter(x => x.message != "") //Quitamos mensajes en blanco.
var inicio = laLista[i].search('%msjant_'); var inicio = laLista[i].search('%msjant_');
var final = laLista[i].indexOf("%", inicio+1); var final = laLista[i].indexOf("%", inicio+1);
var subStr = laLista[i].substring(inicio, final+1); var subStr = laLista[i].substring(inicio, final+1);
console.log("Substr = |" + subStr + "|"); // console.log("Substr = |" + subStr + "|");
var partes = subStr.toString().split('_'); var partes = subStr.toString().split('_');
if(partes.length > 1){ if(partes.length > 1){
console.log("Partes[1] = |" + partes[1] + "|"); // console.log("Partes[1] = |" + partes[1] + "|");
let posicion0 = partes[1].substring(0, partes[1].length-1) let posicion0 = partes[1].substring(0, partes[1].length-1)
console.log("Posicion0 = |" + posicion0 + "|"); // console.log("Posicion0 = |" + posicion0 + "|");
posicion = ((posicion0*1) + 1); posicion = ((posicion0*1) + 1);
console.log("Posicion = " + posicion); // console.log("Posicion = " + posicion);
console.log( elHistorial.length ); // console.log( elHistorial.length );
console.log((elHistorial.length*1)-posicion); // console.log((elHistorial.length*1)-posicion);
console.log("Mensaje="+elHistorial[elHistorial.length - posicion]["message"]) // console.log("Mensaje="+elHistorial[elHistorial.length - posicion]["message"])
elTexto = elTexto.toString().replace(subStr, elHistorial[elHistorial.length - posicion]["message"]); elTexto = elTexto.toString().replace(subStr, elHistorial[elHistorial.length - posicion]["message"].trim());
} }
// histlMsjs = elHistorial["messages"]; // histlMsjs = elHistorial["messages"];
// totalMsjs = histlMsjs.length-1; // totalMsjs = histlMsjs.length-1;
@@ -290,6 +349,21 @@ function remplazos(elTexto, extraInfo){
} }
// return histlMsjs; // return histlMsjs;
} }
if (laLista[i].search('%body%')>-1){//Remplaza con el body del ctx.
const {theMsg} = extraInfo;
const { body } = theMsg
elTexto = elTexto.toString().replace('%body%', body);
}
if (laLista[i].search('%from%')>-1){//Remplaza con el from del ctx.
const {theMsg} = extraInfo;
const { from } = theMsg
elTexto = elTexto.toString().replace('%from%', from);
}
if (laLista[i].search('%solonumero%')>-1){//Remplaza con el from del ctx.
const {theMsg} = extraInfo;
const { from } = theMsg
elTexto = elTexto.toString().replace('%solonumero%', from.replace('@c.us', ''));
}
if (laLista[i].search('%nombre%')>-1){//Remplaza con el nombre del remitente. if (laLista[i].search('%nombre%')>-1){//Remplaza con el nombre del remitente.
if(typeof extraInfo !== undefined){ if(typeof extraInfo !== undefined){
const {theMsg} = extraInfo; const {theMsg} = extraInfo;
@@ -308,7 +382,7 @@ function remplazos(elTexto, extraInfo){
} }
} }
// console.log("EL TEXTO="+elTexto); // console.log("EL TEXTO="+elTexto);
return elTexto return elTexto.trim()
} }
/** /**
@@ -319,22 +393,27 @@ function remplazos(elTexto, extraInfo){
if(resps[step]!=undefined){pasoRequerido=resps[step].pasoRequerido}else{pasoRequerido=null} if(resps[step]!=undefined){pasoRequerido=resps[step].pasoRequerido}else{pasoRequerido=null}
if((pasoRequerido != null && pasoRequerido == ultimoStep)){ if((pasoRequerido != null && pasoRequerido == ultimoStep)){
// console.log("REQUIERE PASO PREVIO Y CUMPLE"); // console.log("REQUIERE PASO PREVIO Y CUMPLE");
cumplePasoPrevio = true; cumplePasoPrevio[elNum] = true;
} }
else if((pasoRequerido != null && pasoRequerido != pasoAnterior[elNum])){ else if((pasoRequerido != null && pasoRequerido != pasoAnterior[elNum])){
// console.log("REQUIERE PASO PREVIO Y NO LO CUMPLE"); // console.log("REQUIERE PASO PREVIO Y NO LO CUMPLE");
cumplePasoPrevio = false; cumplePasoPrevio[elNum] = false;
} }
else{ else{
// console.log("NO REQUIERE PASO PREVIO") // console.log("NO REQUIERE PASO PREVIO")
cumplePasoPrevio = true; cumplePasoPrevio[elNum] = true;
} }
pasoAnterior[elNum] = step pasoAnterior[elNum] = step
ultimoPaso = pasoRequerido; // ultimoPaso = pasoRequerido;
} }
const fs = require('fs'); /**
* Revisa que exista el archivo "chats/numero.json"
* @param {*} theFile
* @returns
*/
function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el archivo "chats/numero.json" function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el archivo "chats/numero.json"
const fs = require('fs');
if (fs.existsSync(theFile)) { if (fs.existsSync(theFile)) {
// console.log("Si existe el archivo "+ theFile); // console.log("Si existe el archivo "+ theFile);
var h = true; var h = true;
@@ -344,4 +423,59 @@ function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el a
var h = false; var h = false;
} }
return h; return h;
}
/**
* Regresa el tiempo tanscurrido en (datepart) desde la ultima visita.\n
* datepart: 'y', 'm', 'w', 'd', 'h', 'n', 's' (default = n)
* @param {*} file
* @param {*} datepart
*/
function traeUltimaVisita(file, datepart = 'n'){
// Node.js program to demonstrate the
// fs.futimes() method
let thisLog = false
const fs = require('fs');
let theFile = `${__dirname}/../chats/`+file+".json"
if(thisLog) console.log("chkFile=", chkFile(theFile), datepart)
if(chkFile(theFile)){
// Get the file descriptor of the file
const fd = fs.openSync(theFile);
// console.log("Details before changing time:");
// Get the stats object of the file
if(thisLog) console.log(new Date())
prevStats = fs.statSync(theFile);
// Access the modified and access time of the file
if(thisLog) console.log("Modification Time:", prevStats.mtime);
if(thisLog) console.log("Access Time:", prevStats.atime);
// Get the current time to change the timestamps
let changedModifiedTime = new Date();
let changedAccessTime = new Date();
// Use the futimes() function to assign
// the new timestamps to the file descriptor
fs.futimes(fd, changedAccessTime, changedModifiedTime, ()=>{})
if(thisLog) console.log("dd=", dateDiff(datepart, prevStats.atime, changedAccessTime))
if(thisLog) console.log(new Date())
return dateDiff(datepart, prevStats.atime, changedAccessTime)
}
else { return 0 }
}
/**
* Regresa el tiempo transcurrido en (datepart) entre las fechas dadas.
* datepart: 'y', 'm', 'w', 'd', 'h', 'n', 's'
* @param {*} datepart
* @param {*} fromdate
* @param {*} todate
* @returns
*/
function dateDiff(datepart, fromdate, todate){
datepart = datepart.toLowerCase();
var diff = todate - fromdate;
var divideBy = { w:604800000,
d:86400000,
h:3600000,
n:60000,
s:1000 };
return Math.floor( diff/divideBy[datepart]);
} }

394
adapter/test.js Normal file
View File

@@ -0,0 +1,394 @@
+++++++++++++++++++++++++++++++++++++ INICIO +++++++++++++++++++++++++++++++++++++++
HORA:4:55:56 PM FROM:5215519561677@c.us, BODY:/Guna, HASMEDIA:false
NUEVA RESPUESTA= Mensaje de getGunaCats
############# Encontramos Funcion, ejecutamos funcion getGunaCats
1 { id: 'CHOCOLATE', title: 'CHOCOLATE' }
2 { id: 'DULCES', title: 'DULCES' }
lasOpciones=[object Object]
List {
description: 'Buenas tardes, selecciona una categoría 👇🏽',
buttonText: 'Ver las categorías',
title: 'Categorías',
footer: 'Selecciona',
sections: [ { title: 'Categorías', rows: [Array] } ]
}
<ref *1> Client {
_events: [Object: null prototype] {
qr: [Function (anonymous)],
ready: [Function (anonymous)],
auth_failure: [Function (anonymous)],
authenticated: [Function (anonymous)],
message: [AsyncFunction (anonymous)],
message_create: [AsyncFunction (anonymous)]
},
_eventsCount: 6,
_maxListeners: undefined,
options: {
authStrategy: LocalAuth {
dataPath: 'C:\\Users\\cheve\\Documents\\GitHub\\botDemoGuna\\.wwebjs_auth',
clientId: undefined,
client: [Circular *1],
userDataDir: 'C:\\Users\\cheve\\Documents\\GitHub\\botDemoGuna\\.wwebjs_auth\\session'
},
puppeteer: {
headless: true,
args: [Array],
defaultViewport: null,
userDataDir: 'C:\\Users\\cheve\\Documents\\GitHub\\botDemoGuna\\.wwebjs_auth\\session'
},
authTimeoutMs: 0,
qrMaxRetries: 0,
takeoverOnConflict: false,
takeoverTimeoutMs: 0,
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
ffmpegPath: 'ffmpeg',
bypassCSP: false
},
authStrategy: LocalAuth {
dataPath: 'C:\\Users\\cheve\\Documents\\GitHub\\botDemoGuna\\.wwebjs_auth',
clientId: undefined,
client: [Circular *1],
userDataDir: 'C:\\Users\\cheve\\Documents\\GitHub\\botDemoGuna\\.wwebjs_auth\\session'
},
pupBrowser: <ref *2> Browser {
eventsMap: Map(2) { 'targetcreated' => [], 'targetchanged' => [] },
emitter: {
all: [Map],
on: [Function: on],
off: [Function: off],
emit: [Function: emit]
},
_ignoredTargets: Set(0) {},
_ignoreHTTPSErrors: false,
_defaultViewport: null,
_process: ChildProcess {
_events: [Object: null prototype],
_eventsCount: 1,
_maxListeners: undefined,
_closesNeeded: 2,
_closesGot: 0,
connected: false,
signalCode: null,
exitCode: null,
killed: false,
spawnfile: 'C:\\Users\\cheve\\Documents\\GitHub\\botDemoGuna\\node_modules\\puppeteer\\.local-chromium\\win64-982053\\chrome-win\\chrome.exe',
_handle: [Process],
spawnargs: [Array],
pid: 7188,
stdin: [Socket],
stdout: null,
stderr: [Socket],
stdio: [Array],
[Symbol(kCapture)]: false
},
_screenshotTaskQueue: TaskQueue { _chain: [Promise] },
_connection: Connection {
eventsMap: [Map],
emitter: [Object],
_lastId: 372,
_sessions: [Map],
_closed: false,
_callbacks: Map(0) {},
_url: 'ws://127.0.0.1:49386/devtools/browser/8ba98a74-7751-45aa-8256-8f82b8312e65',
_delay: 0,
_transport: [NodeWebSocketTransport]
},
_closeCallback: [Function: bound close],
_targetFilterCallback: [Function (anonymous)],
_defaultContext: BrowserContext {
eventsMap: Map(0) {},
emitter: [Object],
_connection: [Connection],
_browser: [Circular *2],
_id: undefined
},
_contexts: Map(0) {},
_targets: Map(5) {
'4904d96d-4dec-4069-95d8-fe7d70f62b06' => [Target],
'71cc8c5e-8516-49de-9387-b2940074aea5' => [Target],
'C7071524BC87DF4C8E9569AD3FBB7348' => [Target],
'1D7791C3C62A14FB306A0ABD1CD86677' => [Target],
'969B67293789E4A52B827E4619DF58D7' => [Target]
}
},
pupPage: <ref *3> Page {
eventsMap: Map(1) { 'framenavigated' => [Array] },
emitter: {
all: [Map],
on: [Function: on],
off: [Function: off],
emit: [Function: emit]
},
_closed: false,
_timeoutSettings: TimeoutSettings {
_defaultTimeout: null,
_defaultNavigationTimeout: null
},
_pageBindings: Map(12) {
'loadingScreen' => [AsyncFunction (anonymous)],
'qrChanged' => [AsyncFunction (anonymous)],
'onAddMessageEvent' => [Function (anonymous)],
'onChangeMessageTypeEvent' => [Function (anonymous)],
'onChangeMessageEvent' => [Function (anonymous)],
'onRemoveMessageEvent' => [Function (anonymous)],
'onMessageAckEvent' => [Function (anonymous)],
'onMessageMediaUploadedEvent' => [Function (anonymous)],
'onAppStateChangedEvent' => [AsyncFunction (anonymous)],
'onBatteryStateChangedEvent' => [Function (anonymous)],
'onIncomingCall' => [Function (anonymous)],
'onReaction' => [Function (anonymous)]
},
_javascriptEnabled: true,
_workers: Map(1) { '96E97F3B444D00EB81EFEFDBC3128749' => [WebWorker] },
_fileChooserInterceptors: Set(0) {},
_userDragInterceptionEnabled: false,
_handlerMap: WeakMap { <items unknown> },
_client: CDPSession {
eventsMap: [Map],
emitter: [Object],
_callbacks: Map(0) {},
_connection: [Connection],
_targetType: 'page',
_sessionId: '44F15C73737F3B036CBCBE340984F10E'
},
_target: Target {
_targetInfo: [Object],
_browserContext: [BrowserContext],
_targetId: 'C7071524BC87DF4C8E9569AD3FBB7348',
_sessionFactory: [Function (anonymous)],
_ignoreHTTPSErrors: false,
_defaultViewport: null,
_screenshotTaskQueue: [TaskQueue],
_pagePromise: [Promise],
_workerPromise: null,
_initializedCallback: [Function (anonymous)],
_initializedPromise: [Promise],
_closedCallback: [Function (anonymous)],
_isClosedPromise: [Promise],
_isInitialized: true
},
_keyboard: Keyboard {
_modifiers: 0,
_pressedKeys: Set(0) {},
_client: [CDPSession]
},
_mouse: Mouse {
_x: 0,
_y: 0,
_button: 'none',
_client: [CDPSession],
_keyboard: [Keyboard]
},
_touchscreen: Touchscreen { _client: [CDPSession], _keyboard: [Keyboard] },
_accessibility: Accessibility { _client: [CDPSession] },
_frameManager: FrameManager {
eventsMap: [Map],
emitter: [Object],
_frames: [Map],
_contextIdToContext: [Map],
_isolatedWorlds: [Set],
_client: [CDPSession],
_page: [Circular *3],
_networkManager: [NetworkManager],
_timeoutSettings: [TimeoutSettings],
_mainFrame: [Frame]
},
_emulationManager: EmulationManager {
_emulatingMobile: false,
_hasTouch: false,
_client: [CDPSession]
},
_tracing: Tracing { _recording: false, _path: '', _client: [CDPSession] },
_coverage: Coverage { _jsCoverage: [JSCoverage], _cssCoverage: [CSSCoverage] },
_screenshotTaskQueue: TaskQueue { _chain: [Promise] },
_viewport: null
},
info: ClientInfo {
pushname: 'Omega',
wid: {
server: 'c.us',
user: '5215527026728',
_serialized: '5215527026728@c.us'
},
me: {
server: 'c.us',
user: '5215527026728',
_serialized: '5215527026728@c.us'
},
phone: undefined,
platform: 'android'
},
interface: InterfaceController {
pupPage: <ref *3> Page {
eventsMap: [Map],
emitter: [Object],
_closed: false,
_timeoutSettings: [TimeoutSettings],
_pageBindings: [Map],
_javascriptEnabled: true,
_workers: [Map],
_fileChooserInterceptors: Set(0) {},
_userDragInterceptionEnabled: false,
_handlerMap: [WeakMap],
_client: [CDPSession],
_target: [Target],
_keyboard: [Keyboard],
_mouse: [Mouse],
_touchscreen: [Touchscreen],
_accessibility: [Accessibility],
_frameManager: [FrameManager],
_emulationManager: [EmulationManager],
_tracing: [Tracing],
_coverage: [Coverage],
_screenshotTaskQueue: [TaskQueue],
_viewport: null
}
},
theMsg: Message {
_data: {
id: [Object],
body: '/Guna',
type: 'chat',
t: 1675378555,
notifyName: 'Alfredo',
from: '5215519561677@c.us',
to: '5215527026728@c.us',
self: 'in',
ack: 1,
isNewMsg: true,
star: false,
kicNotified: false,
recvFresh: true,
isFromTemplate: false,
pollInvalidated: false,
isSentCagPollCreation: false,
latestEditMsgKey: null,
latestEditSenderTimestampMs: null,
broadcast: false,
mentionedJidList: [],
isVcardOverMmsDocument: false,
isForwarded: false,
hasReaction: false,
productHeaderImageRejected: false,
lastPlaybackProgress: 0,
isDynamicReplyButtonsMsg: false,
isMdHistoryMsg: false,
stickerSentTs: 0,
isAvatar: false,
requiresDirectConnection: false,
pttForwardedFeaturesEnabled: true,
isEphemeral: false,
isStatusV3: false,
links: []
},
mediaKey: undefined,
id: {
fromMe: false,
remote: '5215519561677@c.us',
id: '3A98BA96F6922B404213',
_serialized: 'false_5215519561677@c.us_3A98BA96F6922B404213'
},
ack: 1,
hasMedia: false,
body: '/Guna',
type: 'chat',
timestamp: 1675378555,
from: '5215519561677@c.us',
to: '5215527026728@c.us',
author: undefined,
deviceType: 'ios',
isForwarded: false,
forwardingScore: 0,
isStatus: false,
isStarred: false,
broadcast: false,
fromMe: false,
hasQuotedMsg: false,
duration: undefined,
location: undefined,
vCards: [],
inviteV4: undefined,
mentionedIds: [],
orderId: undefined,
token: undefined,
isGif: false,
isEphemeral: false,
links: [],
numero: '5215519561677@c.us',
key: 'gunaCats',
lastStep: null,
step: 'gunaCats',
trigger: null,
replyMessage: 'Mensaje de getGunaCats'
},
[Symbol(kCapture)]: false
}
+++++++++++++++++++++++++++++++++++++ INICIO +++++++++++++++++++++++++++++++++++++++
HORA:4:56:00 PM FROM:5215519561677@c.us, BODY:DULCES, HASMEDIA:false
======= KEY ES NULO USAMOS REGEXP =======
KEY=|doblemensaje|
Esta Key=doblemensaje - pasoReq=menu - PasoAnt=undefined|gunaCats
NO CUMPLE PASO REQ
pasoReq=menu - PasoAnt=undefined
KEY=|recibenombre|
Esta Key=recibenombre - pasoReq=opcion3 - PasoAnt=undefined|gunaCats
NO CUMPLE PASO REQ
pasoReq=opcion3 - PasoAnt=undefined
KEY=|gRevisaCliente|
Esta Key=gRevisaCliente - pasoReq=gallina - PasoAnt=undefined|gunaCats
NO CUMPLE PASO REQ
pasoReq=gallina - PasoAnt=undefined
KEY=|gGuardainfo|
Esta Key=gGuardainfo - pasoReq=gRevisaCliente - PasoAnt=undefined|gunaCats
NO CUMPLE PASO REQ
pasoReq=gRevisaCliente - PasoAnt=undefined
KEY=|paq3|
Esta Key=paq3 - pasoReq=menu - PasoAnt=undefined|gunaCats
NO CUMPLE PASO REQ
pasoReq=menu - PasoAnt=undefined
KEY=|Desbloqueo|
Esta Key=Desbloqueo - pasoReq=soporte - PasoAnt=undefined|gunaCats
NO CUMPLE PASO REQ
pasoReq=soporte - PasoAnt=undefined
KEY=|gunaCats2|
Esta Key=gunaCats2 - pasoReq=gunaCats - PasoAnt=undefined|gunaCats
NUEVA RESPUESTA= Mensaje de getGunaCats2
############# Encontramos Funcion, ejecutamos funcion getGunaSubtipo
1 { id: 'KINDER', title: 'KINDER' }
2 { id: 'CHOCOLATE', title: 'CHOCOLATE' }
lasOpciones=undefined
+++++++++++++++++++++++++++++++++++++ INICIO +++++++++++++++++++++++++++++++++++++++
HORA:4:56:05 PM FROM:5215519561677@c.us, BODY:CHOCOLATE, HASMEDIA:false
======= KEY ES NULO USAMOS REGEXP =======
KEY=|doblemensaje|
Esta Key=doblemensaje - pasoReq=menu - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=menu - PasoAnt=undefined
KEY=|recibenombre|
Esta Key=recibenombre - pasoReq=opcion3 - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=opcion3 - PasoAnt=undefined
KEY=|gRevisaCliente|
Esta Key=gRevisaCliente - pasoReq=gallina - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=gallina - PasoAnt=undefined
KEY=|gGuardainfo|
Esta Key=gGuardainfo - pasoReq=gRevisaCliente - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=gRevisaCliente - PasoAnt=undefined
KEY=|paq3|
Esta Key=paq3 - pasoReq=menu - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=menu - PasoAnt=undefined
KEY=|Desbloqueo|
Esta Key=Desbloqueo - pasoReq=soporte - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=soporte - PasoAnt=undefined
KEY=|gunaCats2|
Esta Key=gunaCats2 - pasoReq=gunaCats - PasoAnt=undefined|gunaCats2
NO CUMPLE PASO REQ
pasoReq=gunaCats - PasoAnt=undefined
KEY=|gunaProds|
Esta Key=gunaProds - pasoReq=gunaCats2 - PasoAnt=undefined|gunaCats2
NUEVA RESPUESTA= Mensaje de getGunaCats2
############# Encontramos Funcion, ejecutamos funcion getGunaProds

705
app.js
View File

@@ -5,67 +5,82 @@ require('dotenv').config()
const fs = require('fs'); const fs = require('fs');
const express = require('express'); const express = require('express');
global.siguientePaso = [{"numero":"1", "va":"XXX"}]; //MOD by CHV - Agregamos para pasar el VAMOSA a "index.js" global.siguientePaso = [{"numero":"1", "va":"XXX"}]; //MOD by CHV - Agregamos para pasar el VAMOSA a "index.js"
global.pasoAnterior = [];
const cors = require('cors') const cors = require('cors')
const axios = require('axios').default;//MOD by CHV - Agregamos para el get del "/URL" const axios = require('axios').default;//MOD by CHV - Agregamos para el get del "/URL"
const qrcode = require('qrcode-terminal'); const qrcode = require('qrcode-terminal');
const { Client, LocalAuth, Buttons, List } = require('whatsapp-web.js'); const { Client, LocalAuth, Buttons, List } = require('whatsapp-web.js');
const mysqlConnection = require('./config/mysql') const mysqlConnection = require('./config/mysql')
const { middlewareClient } = require('./middleware/client') // const { middlewareClient } = require('./middleware/client')
const { generateImage, cleanNumber, checkEnvFile, createClient, isValidNumber } = require('./controllers/handle') const { generateImage, cleanNumber, checkEnvFile, createClient, isValidNumber } = require('./controllers/handle')
const { connectionReady, connectionLost } = require('./controllers/connection') const { connectionReady, connectionLost } = require('./controllers/connection')
const { saveMedia, saveMediaToGoogleDrive } = require('./controllers/save') const { saveMedia, saveMediaToGoogleDrive } = require('./controllers/save')
const { getMessages, responseMessages, bothResponse, waitFor } = require('./controllers/flows') const { getMessages, responseMessages, bothResponse, waitFor } = require('./controllers/flows')
const { sendMedia, sendMessage, lastTrigger, sendMessageButton, sendMessageList, readChat } = require('./controllers/send'); const { sendMedia, sendMessage, lastTrigger, sendMessageButton, sendMessageList, readChat } = require('./controllers/send');
const { remplazos, stepsInitial} = require('./adapter/index');//MOD by CHV - Agregamos para utilizar remplazos y stepsInitial const { remplazos, stepsInitial, vamosA, traeUltimaVisita } = require('./adapter/index');//MOD by CHV - Agregamos para utilizar remplazos y stepsInitial
const { isUndefined } = require('util'); // const { isUndefined } = require('util');
const { isSet } = require('util/types'); // const { isSet } = require('util/types');
const { Console } = require('console'); const { Console } = require('console');
const { ClientRequest } = require('http'); // const { ClientRequest } = require('http');
const { guardaXLSDatos, leeXLSDatos} = require('./Excel');
// const { ContextsClient } = require('@google-cloud/dialogflow');
const { ingresarDatos, leerDatos } = require('./implementaciones/sheets')
const app = express(); const app = express();
app.use(cors()) app.use(cors())
app.use(express.json()) app.use(express.json())
const MULTI_DEVICE = process.env.MULTI_DEVICE || 'true'; const MULTI_DEVICE = process.env.MULTI_DEVICE || 'true';
const server = require('http').Server(app) const server = require('http').Server(app)
const port = process.env.PORT || 3000 const port = process.env.PORT || 3000
const delay = (ms) => new Promise((resolve) => setTimeout(resolve,ms))
var client; var client;
var dialogflowFilter = false; var dialogflowFilter = false;
var totalMsjs; //MOD by CHV - // var totalMsjs; //MOD by CHV -
var vamosA = ""; //MOD by CHV - // var vamosA = ""; //MOD by CHV -
var newBody; //MOD by CHV - var newBody; //MOD by CHV -
var nuevaRespuesta; //MOD by CHV - Se agrego para los remplazos var nuevaRespuesta; //MOD by CHV - Se agrego para los remplazos
var vars = []
app.use('/', require('./routes/web')) app.use('/', require('./routes/web'))
let blackList = ['34692936038', '34678310819', '34660962689', '34649145761','34630283553','34648827637','34630255646','14178973313']
/**
* Escuchamos cuando entre un mensaje /**
*/ * Escuchamos cuando entre un mensaje
const listenMessage = () => client.on('message', async msg => { */
listenMessage = () => client.on('message', async msg => {
const { from, body, hasMedia } = msg; const { from, body, hasMedia } = msg;
// console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); if (vars[from] === undefined) vars[from] = []
console.log("+++++++++++++++++++++++++++++++++++++ INICIO +++++++++++++++++++++++++++++++++++++++"); console.log("+++++++++++++++++++++++++++++++++++++ INICIO +++++++++++++++++++++++++++++++++++++++");
// console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
client.theMsg = msg; client.theMsg = msg;
console.log("HORA:"+new Date().toLocaleTimeString()+" FROM:"+from+", BODY:"+body+", HASMEDIA:"+hasMedia+", DEVICETYPE:"+client.theMsg?.deviceType);
console.log("HORA:"+new Date().toLocaleTimeString()+" FROM:"+from+", BODY:"+body+", HASMEDIA:"+hasMedia);
newBody = removeDiacritics(body) //MOD by CHV - Agregamos para quitar acentos newBody = removeDiacritics(body) //MOD by CHV - Agregamos para quitar acentos
// newBody = remplazos(newBody);
vamosA = ""; // const uv = traeUltimaVisita(from, 's')
// console.log("ultVista=", uv)
if(!isValidNumber(from)){ if(!isValidNumber(from)){
return return
} }
// Este bug lo reporto Lucas Aldeco Brescia para evitar que se publiquen estados // Este bug lo reporto Lucas Aldeco Brescia para evitar que se publiquen estados
if (from === 'status@broadcast') { if (from === 'status@broadcast') { return }
return /**
* Blacklist, los telefonos incluidos en este arreglo son ignorados por el bot.
*/
if (blackList.includes(from.replace("@c.us",""))) {
console.log('BlackListed: ',blackList.includes(from.replace("@c.us","")))
return
} }
message = newBody.toLowerCase(); message = newBody.toLowerCase();
const number = cleanNumber(from) const number = cleanNumber(from)
client.theMsg['numero'] = number
// Guardamos el mensaje en Google Sheets
ingresarDatos(from, body)
// console.log(stepsInitial)
var { key } = stepsInitial.find(k => k.keywords.includes(message)) || { key: null }//MOD by CHV - Se agrega para obtener KEY var { key } = stepsInitial.find(k => k.keywords.includes(message)) || { key: null }//MOD by CHV - Se agrega para obtener KEY
await readChat(number, message, null , key) //MOD by CHV - Agregamos key/regla para guardarla en "chats/numero.json" await readChat(number, message, null , key) //MOD by CHV - Agregamos key/regla para guardarla en "chats/numero.json"
client.theMsg['key'] = key
/** /**
* Guardamos el archivo multimedia que envia * Guardamos el archivo multimedia que envia
*/ */
@@ -77,7 +92,6 @@ const listenMessage = () => client.on('message', async msg => {
/** /**
* Si estas usando dialogflow solo manejamos una funcion todo es IA * Si estas usando dialogflow solo manejamos una funcion todo es IA
*/ */
if (process.env.DATABASE === 'dialogflow') { if (process.env.DATABASE === 'dialogflow') {
if (process.env.DIALOGFLOW_MEDIA_FOR_SLOT_FILLING === 'true' && dialogflowFilter) { if (process.env.DIALOGFLOW_MEDIA_FOR_SLOT_FILLING === 'true' && dialogflowFilter) {
waitFor(_ => hasMedia, 30000) waitFor(_ => hasMedia, 30000)
@@ -106,6 +120,7 @@ const listenMessage = () => client.on('message', async msg => {
} }
if(body=='/listas'){ if(body=='/listas'){
// Asi se manda directamente con el ciente de whatsapp-web.js "client.sendMessage(from, productList)"
const productList = new List( const productList = new List(
"Here's our list of products at 50% off", "Here's our list of products at 50% off",
"View all products", "View all products",
@@ -122,169 +137,491 @@ const listenMessage = () => client.on('message', async msg => {
"Please select a product" "Please select a product"
); );
console.log('##################################################################################################') console.log('##################################################################################################')
// console.log(from, lista) console.log("****************** productList ******************")
// let sections = [{title:'sectionTitle',rows:[{id:'ListItem1', title: 'title1'},{id:'ListItem2', title:'title2'}]}]; console.log(productList)
// let lista = new List('List body','btnText',sections,'Title','footer'); client.sendMessage(from, productList);
console.log("****************** productList ******************") // Asi se manda directamente con la funcion del bot. "sendMessageList(client, from, null, lista)"
console.log(productList) // let sections = [
client.sendMessage(from, productList); //cliente.sendMessage recibe el arreglo SIN nombres (solo las secciones los necesitan) // { title:'sectionTitle',
// client.sendMessage('5215527049036@c.us', productList); // rows:[
// client.sendMessage('5215554192439@c.us', productList); // {id:'ListItem1', title: 'title1'},
// await sendMessageList(client, '5215545815654@c.us', null, lista); //sendMessageList recibe el arreglo CON nombres, como viene del response.json // {id:'ListItem2', title:'title2'}
// await sendMessageList(client, '5215527049036@c.us', null, lista); // ]
// await sendMessageList(client, '5215554192439@c.us', null, lista); // }
// client.sendMessage(from, lista); // ];
// let lista = new List('List body','btnText',sections,'Title','footer');
await sendMessageList(client, from, null, productList); //sendMessageList recibe el arreglo CON nombres, tal cual se usa en "response.json"
} }
/**
* PRUEBA BOTONES NUEVOS
*/
// if(body=="579"){
// const buttons_reply = new Buttons("Por favor vuelve a intentar, mandando *SOLO* la palabra *gallina* con una diagonal al principio 👇🏽 \n\n */gallina*\n ", [{body: "/gallina", id: 'errorGallina'}], 'Error', 'O haz clic en el siguiente botón') // Reply button
// for (const component of [buttons_reply]) await client.sendMessage(from, component);
// }
/** /**
* Ver si viene de un paso anterior * Ver si viene de un paso anterior
* Aqui podemos ir agregando más pasos * Aqui podemos ir agregando más pasos
* a tu gusto! * a tu gusto!
*/ */
// const lastStep = await lastTrigger(from) || null;
const lastStep = await lastTrigger(from) || null; // client.theMsg['lastStep'] = lastStep
// console.log("LAST STEP="+lastStep+", FROM:"+from); // // console.log("LAST STEP="+lastStep+", FROM:"+from);
if (lastStep) { // if (lastStep) {
const response = await responseMessages(lastStep) // const response = await responseMessages(lastStep)
console.log("CLIENT="+client+", FROM:"+from+", REPLYMESSAGE:"+response.replyMessage); // client.theMsg['trigger'] = response.trigger
// await sendMessage(client, from, response.replyMessage, lastStep); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo. // console.log("CLIENT="+client+", FROM:"+from+", REPLYMESSAGE:"+response.replyMessage);
response.replyMessage.forEach( async messages => { // // await sendMessage(client, from, response.replyMessage, lastStep); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo.
var thisMsg = messages.mensaje // response.replyMessage.forEach( async messages => {
if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')} // var thisMsg = messages.mensaje
await sendMessage(client, from, remplazos(thisMsg, client), response.trigger); // if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')}
}) // await sendMessage(client, from, remplazos(thisMsg, client), response.trigger);
} // })
// }
/** /**
* Respondemos al primero paso si encuentra palabras clave * Respondemos al primero paso si encuentra palabras clave
*/ */
// const step = await getMessages(message, );
// console.log("STEP - "+step+"|"+message);
// console.log("****** STEP="+step);
// console.log("****** MESSAGE:"+message);
const step = await getMessages(message, from); const step = await getMessages(message, from);
client.theMsg['step'] = step
if (step) { if (step) {
// console.log("Entramos a STEP")
const response = await responseMessages(step); const response = await responseMessages(step);
// console.log("URL:"+nuevaRespuesta); client.theMsg['trigger'] = response.trigger
// console.log("HAY URL?? : "+nuevaRespuesta.search("/URL"));
var resps = require('./flow/response.json'); var resps = require('./flow/response.json');
nuevaRespuesta = remplazos(resps[step].replyMessage.join(''), client); nuevaRespuesta = remplazos(resps[step].replyMessage.join(''), client);
var pasoRequerido = resps[step].pasoRequerido; client.theMsg['replyMessage'] = nuevaRespuesta
// var hayRequest = false; // var pasoRequerido = resps[step].pasoRequerido;
// if(hayRequest==false && nuevaRespuesta.search("/URL")>-1){console.log("Paramos flujo para que no mande el mensaje '/URL'."); return;}//Si el trigger es desbloqueo ya no hace nada mas. if(body=='traeXLS'){
const rows = await leeXLSDatos('x')
console.log("RESULTADOS:")
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function retardo() {
for (sp=1;sp<rows.length;sp++) {
// console.log(masivo[sp].numero+"@c.us");
var rnd = getRandomInt(1,7); // Random entre 1 y 6 segundos.
if(sp % 15 === 0){console.log("******** VAN 15, HACEMOS PAUSA DE 10 SEGUNDOS ********"); await sleep(10000);} //
console.log(`============= Mandamos el mensaje ${sp} ==============`);
var elTextoDelMensaje = `%saludo% ${rows[sp].prefijo} *${rows[sp].nombre}* con CARNET *${rows[sp].carnet}*, le saludamos de _CORPORACION AZUL_ le escribimos para recordarle que tiene un pago *pendiente* que se vence el *02/02/2023*`;
await sleep(500);
// let elNumero = '51968016860@c.us'
let elNumero = '5215554192439@c.us'
client.sendMessage(elNumero, remplazos(elTextoDelMensaje, client));
console.log(`Esperamos ${rnd} segundos...`);
await sleep(rnd*1000);
}
console.log('Terminamos');
}
retardo();
}
/*
============================================================================
========================== ENVIO MASIVO TEST ===========================
============================================================================
*/
if(message=='/spam'){
const masivo = require('./spam.json')
var saludo;
var caritas;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function retardo() {
for (sp=0;sp<masivo.length;sp++) {
console.log(masivo[sp].numero+"@c.us");
var rnd = getRandomInt(1,7); // Random entre 1 y 6 segundos.
if(rnd==1||rnd==4){saludo = "Hola ";}
else if(rnd==2||rnd==5){saludo = "Saludos ";}
else {saludo = "%saludo% ";}
if(rnd==1){caritas = "👨🏻‍🦰👩🏻‍🦰";}
else if(rnd==2){caritas = "👩🏻‍🦰👨🏻‍🦰";}
else if(rnd==3){caritas = "🧔🏽👧🏽";}
else if(rnd==4){caritas = "👧🏽🧔🏽";}
else if(rnd==5){caritas = "👩🏻‍🦰🧔🏽";}
else if(rnd==6){caritas = "🧔🏽👩🏻‍🦰";}
if(sp % 15 === 0){console.log("******** VAN 15, HACEMOS PAUSA DE 10 SEGUNDOS ********"); await sleep(10000);} //
console.log(`============= Mandamos el mensaje ${sp} ==============`);
var elTextoDelMensaje = caritas + " *" + saludo + "amigo tendero* ❗❗👋🏻\n🕊 *GUNA* trae para ti dinámicas digitales, con las que podrás participar para ganar increíbles premios. 🏆💸💰\nSigue los siguientes pasos: 😃\n*1.* 📲Sigue la página de Yo Soy Guna en Facebook en la siguiente liga ➡️ https://www.facebook.com/yosoyguna\n*2.* 👉🏻Es importante des click en el botón Me Gusta 👍\n*3.* 🧐Sigue la dinámica que publicaremos , subiendo tu foto 📸 con los siguientes #yosoyguna #gunatenderos #gunachampions\n*4.* 🥳🎉En esta misma página , podrás ver publicados los ganadores🏅 y el tiempo en que serán elegidos. 💲 Además de tener acceso a increíbles promociones 🤑";
sendMedia(client, masivo[sp].numero+"@c.us", "envioMasivoGuna.jpg");
await sleep(500);
client.sendMessage(masivo[sp].numero+"@c.us", remplazos(elTextoDelMensaje, client));
// client.sendMessage(masivo[i].numero+"@c.us", "Este es un mensaje de prueba para *"+masivo[i].numero+"*, HORA:*"+new Date().toLocaleTimeString()+"*");
console.log(`Esperamos ${rnd} segundos...`);
await sleep(rnd*1000);
}
console.log('Done');
}
retardo();
}
/** /**
* Si quieres enviar botones * Llama el API para traer categorias de Guna.
* @param {*} ctx El objeto del mensaje.
*/ */
async function getGunaCats(ctx) {
let theUrl = `http://localhost:8888/dbrquery?j={"query":"selectTipoFerreroMty","exec":"ExecuteQuery","params":{"par1":"xxx"}}`
const RES = await axios.get(theUrl).then(function (response) {
let lasOpciones = []
for(reg=0;reg<response.data.respuesta.length;reg++) {
let tempItem = {}
tempItem['id']=response.data.respuesta[reg].CAT_PT_DESC
tempItem['title']=response.data.respuesta[reg].CAT_PT_DESC
lasOpciones.push(tempItem)
console.log(lasOpciones.length, tempItem)
}
// console.log("lasOpciones="+lasOpciones[1])
const productList = new List(
remplazos("%saludo%, selecciona una categoría 👇🏽"),
"Ver las categorías",
[
{ title: "Categorías",
rows: lasOpciones,
}
],
"Categorías",
"Selecciona"
)
console.log(productList)
client.sendMessage(from, productList)
// console.log(ctx)
// sendMessagList(client, from, null, productList);
return "1"
}).catch(function (error) {
console.log(error);
return error
});
}
/**
* Llama el API para traer subcategorias de Guna.
* @param {*} ctx El objeto del mensaje.
*/
async function getGunaSubtipo(ctx) {
let par1 = ctx.theMsg.body
vars[from]['tipo'] = ctx.theMsg.body
// console.log("V_TIPO=", from, vars[from]['tipo'])
let theUrl = `http://localhost:8888/dbrquery?j={"query":"selectSubtipoFerreroMty","exec":"ExecuteQuery","params":{"par1":"${vars[from]['tipo']}"}}`
const RES = await axios.get(theUrl).then(function (response) {
if( response.data.respuesta.length == 0 ) {
console.log("No hay resultados",from)
vamosA(from, "gunaCats")
client.sendMessage(from, "Esa categoría *no existe*, por favor revisa y vuelve a intentar.")
}
let elMensaje = "Gracias,\nAhora una subcategoría:\n\n"
let lasOpciones = []
for(reg=0;reg<response.data.respuesta.length;reg++) {
let tempItem = {}
tempItem['id']=response.data.respuesta[reg].CAT_PS_DESC
tempItem['title']=response.data.respuesta[reg].CAT_PS_DESC
lasOpciones.push(tempItem)
console.log(lasOpciones.length, tempItem)
}
// console.log("lasOpciones="+lasOpciones[3])
const productList = new List(
"Selecciona una subcategoria 👇🏽",
"Ver las subcategorías",
[
{ title: "Subcategorías",
rows: lasOpciones,
}
],
`CATEGORÍA ${body}`
)
client.sendMessage(from, productList)
return "1"
}).catch(function (error) {
console.log(error);
return error
});
}
/**
* Llama el API para traer productos de Guna.
* @param {*} ctx El objeto del mensaje.
*/
async function getGunaProds(ctx) {
if(vars[from]['recompra'] === undefined) vars[from]['subtipo'] = ctx.theMsg.body
console.log(vars[from]['tipo'], vars[from]['subtipo'])
let theUrl = `http://localhost:8888/dbrquery?j={"query":"selectProdsFerreroMty","exec":"ExecuteQuery","params":{"par1":"${vars[from]['tipo']}", "par2":"${vars[from]['subtipo']}"}}`
const RES = await axios.get(theUrl).then(function (response) {
let elMensaje = "Gracias,\nAhora un producto:\n\n"
let lasOpciones = []
for(reg=0;reg<response.data.respuesta.length;reg++) {
let tempItem = {}
tempItem['id']=response.data.respuesta[reg].CAT_GP_ID
tempItem['title']=`${response.data.respuesta[reg].CAT_GP_NOMBRE} $${response.data.respuesta[reg].CAT_GP_PRECIO}, INV:${response.data.respuesta[reg].CAT_GP_ALMACEN} `
lasOpciones.push(tempItem)
}
const productList = new List(
"Selecciona un producto 👇🏽",
"Ver los productos",
[
{ title: "Productos",
rows: lasOpciones,
}
],
`SUBCATEGORÍA ${vars[from]['subtipo']}`,
"Footer"
)
client.sendMessage(from, productList)
return "1"
}).catch(function (error) {
console.log(error);
return error
});
}
/**
* Llama el API para traer productos de Guna.
* @param {*} ctx El objeto del mensaje.
*/
async function agregaProds(ctx) {
// vars[from]['subtipo'] = ctx.theMsg.body
if(vars[from]['prods'] === undefined) { vars[from]['prods'] = [] }
let elProd = ctx.theMsg.body
let elMensaje = ""
if(elProd.indexOf(' $') > -1){ // Producto con formato correcto.
vars[from]['ultimoProd'] = elProd
elProd = elProd.substring(0, elProd.indexOf(' $')).trim().toLowerCase()
var precio = ctx.theMsg.body.substring(ctx.theMsg.body.indexOf(' $')+2)
console.log("precio",precio)
precio = precio.substring(0, precio.indexOf(','))
console.log("precio",precio)
vars[from]['prods'][elProd] = {"cant":0, "precio":precio}
console.log("EL_PROD=", elProd)
console.log(vars[from]['prods'])
elMensaje = ctx.theMsg.replyMessage
let re = ctx.theMsg.body.trim().toLowerCase()
elMensaje = elMensaje.replace(re, elProd.toLowerCase())
}
else{ // Producto SIN precio.
elMensaje = "El producto que seleccionaste es *incorrecto*, por favor intenta de nuevo."
sendMessage(client, from, elMensaje, ctx.theMsg.trigger, ctx.theMsg.step);
await delay(500)
vars[from]['recompra'] = true
getGunaProds()
vamosA(from, "gunaProds")
return
}
sendMessage(client, from, elMensaje, ctx.theMsg.trigger, ctx.theMsg.step);
return
}
/**
* Tomamos la cantidad del producto seleccionado.
* @param {*} ctx El objeto del mensaje.
*/
async function prodCantidad(ctx) {
// console.log("Entramos a prodCantidad")
let laCant = ctx.theMsg.body.trim()
const reg = new RegExp(/^\d+$/)
let elProd = vars[from]['ultimoProd'].toLowerCase()
elProd = elProd.substring(0, elProd.indexOf(' $')).trim()
console.log("SOLO NUMS |" + laCant + "|", reg.test(laCant))
if(reg.test(laCant)){
console.log(vars)
console.log("Recibimos cant = " + laCant)
console.log("EL_PROD=", vars[from]['prods'][elProd])
console.log("precio=", vars[from]['prods'][elProd].precio)
vars[from]['prods'][elProd] = {"cant":laCant, "precio":vars[from]['prods'][elProd]['precio']}
var elMensaje = ""
const prods = Object.keys(vars[from]['prods']);
var total = 0
prods.forEach((prod, index) => {
if( vars[from]['prods'][prod] !== undefined && prod[0] !== undefined ){
elMensaje = elMensaje + `${vars[from]['prods'][prod].cant} - ${prod[0].toUpperCase() + prod.substring(1)}\n`
console.log("cant y precio=", vars[from]['prods'][prod].cant, vars[from]['prods'][prod].precio)
if(reg.test(vars[from]['prods'][prod].cant) && vars[from]['prods'][prod].precio != ""){
total = total + (vars[from]['prods'][prod].cant * vars[from]['prods'][prod].precio)
}
}
console.log(prod, vars[from]['prods'][prod]);
});
let pesos = Intl.NumberFormat('en-US')
elMensaje = elMensaje + "\n*Total*: $" + pesos.format(total)
elMensaje = elMensaje + "\n¿Quieres agregar mas productos a tu orden?"
var bts = {
"title":"Tu orden",
"message":elMensaje,
"buttons":[
{"body":" Agregar productos"},
{"body":"⬅️ Cambiar categoría"},
{"body":"✖️ Terminar"}
]
}
sendMessageButton(client, from, "xxx", bts)
}
else{
console.log("NO SOLO NUMS")
vamosA(from, "gunaProdsAgrega")
sendMessage(client, from, "Por favor escribe 👉🏽 *solo* 👈🏽 el número.", response.trigger, step);
}
return "1"
}
/**
* Mandamos nuevamente la lista de productos.
* @param {*} ctx El objeto del mensaje.
*/
async function comprarMas(ctx) {
console.log("Entramos a comprarMas")
vars[from]['recompra'] = true
vamosA(from, "gunaProds")
await getGunaProds(ctx)
vars[from]['recompra'] = false
return "1"
}
/**
* Mandamos nuevamente la lista de categorías.
* @param {*} ctx El objeto del mensaje.
*/
async function terminaCompra(ctx) {
console.log("Entramos a terminaCompra")
vars[from] = []
sendMessage(client, from, "!Gracias por tu compra, regresa pronto!", response.trigger, step);
return
}
/**
* Llama el API para desbloquear un usuario.
* @param {*} ctx El objeto del mensaje.
*/
async function desbloqueaUsuario(ctx) {
let par1 = ctx.theMsg.body
let theUrl = `http://localhost:8888/dbrquery?j={"query":"update_usuario_guna_nobajas","exec":"ExecuteCommand","params":{"par1":"${par1}", "par2":"XXPARAM2XX", "par3":"XXPARAM3XX"}}`
const RES = await axios.get(theUrl).then(function (response) {
const { AffectedRows } = response.data['respuesta'][0]
console.log('AFFECTED_ROWS = ', AffectedRows)
if(response.data['respuesta'][0]['AffectedRows']=="1"){
sendMessage(client, from, "Listo, usuario *"+response.data['params']['par1']+"* desbloqueado, por favor *cerrar navegadores* y reingresar.", response.trigger, step);
}
else{
sendMessage(client, from, "El usuario *"+response.data['params']['par1']+"* no *existe* o esta dado de *baja*, por favor revisarlo y volver a intentar.", response.trigger, step);
}
return response
}).catch(function (error) {
console.log(error);
return error
});
}
/**
* Llama el API para desbloquear el usuario.
*
* @param {*} theURL El URL para llamar al API
* @param {*} step
*/
async function desbloqueaUsuario2(theUrl, step) {
// const {from} = client.theMsg
// const RES = await axios.get(theUrl).then(function (response) {
// const { AffectedRows } = response.data['respuesta'][0]
// console.log('AFFECTED_ROWS = ', AffectedRows)
// if(response.data['respuesta'][0]['AffectedRows']=="1"){
// sendMessage(client, from, "Listo, usuario *"+response.data['params']['par1']+"* desbloqueado, por favor *cerrar navegadores* y reingresar.", response.trigger, step);
// }
// else{
// sendMessage(client, from, "El usuario *"+response.data['params']['par1']+"* no *existe* o esta dado de *baja*, por favor revisarlo y volver a intentar.", response.trigger, step);
// }
// return response
// }).catch(function (error) {
// console.log(error);
// return error
// });
}
// ####################################################################################################################
// ############################## INICIAN FUNCIONES PARA MANEJO DE PARAMETROS #####################################
// ############################## EN EL RESPONSE.JSON #####################################
// ####################################################################################################################
/*
* Si quieres ejecutar una función.
*/
if(response.hasOwnProperty('funcion')){
console.log("############# Encontramos función, ejecutamos la función '" + response.funcion + "'")
laFuncion = response.funcion + "(client)"
eval(laFuncion)
// return
}
if(response.hasOwnProperty('url') && response.hasOwnProperty('values')){
// let theURL = response.url;
// let url0 = theURL
// let vals = response.values // Traemos los valores desde el response.json
// let j = theURL.split('j=')[1] // Traemos el JSON del URL.
// let j2 = JSON.parse(j)
// let cont = 0
// const { params } = j2 // Traemos los parametros del JSON.
// console.log('PARAMS=', params, params['par1'], Object.keys(params).length)
// let url2
// for (const par in params) { // Remplazamos los valores en lo parametros.
// console.log(`${par}: ${params[par]}, ${cont}: ${remplazos(vals[cont], client)}`);
// if(cont==0){url2=url0.replace(params[par], remplazos(vals[cont], client));}
// else {url2=url2.replace(params[par], remplazos(vals[cont], client));}
// cont++
// }
// // console.log('THE_URL=', url2)
// desbloqueaUsuario2(url2, step) //Llamamos al API para desbloquear el usuario.
// return
}
/**
* Si quieres enviar imagen.
*/
if (!response.delay && response.media) { if (!response.delay && response.media) {
// console.log("++++++++++++++++++++++++++++ SEND MEDIA NO DELAY +++++++++++++++++++++++++++++++++++"); // console.log("++++++++++++++++++++++++++++ SEND MEDIA NO DELAY +++++++++++++++++++++++++++++++++++");
sendMedia(client, from, response.media, response.trigger); sendMedia(client, from, response.media, response.trigger);
} }
/**
* Si quieres enviar imagen con retraso.
*/
if (response.delay && response.media) { if (response.delay && response.media) {
setTimeout(() => { setTimeout(() => {
// console.log("++++++++++++++++++++++++++++ SEND MEDIA AND DELAY +++++++++++++++++++++++++++++++++++"); // console.log("++++++++++++++++++++++++++++ SEND MEDIA AND DELAY +++++++++++++++++++++++++++++++++++");
sendMedia(client, from, response.media, response.trigger); sendMedia(client, from, response.media, response.trigger);
}, response.delay) }, response.delay)
} }
/**
* Si quieres enviar mensaje con retraso.
*/
if (response.delay){ if (response.delay){
// await sendMessage(client, from, nuevaRespuesta, response.trigger, step); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo. // await sendMessage(client, from, nuevaRespuesta, response.trigger, step); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo.
response.replyMessage.forEach( async messages => { setTimeout(() => {
var thisMsg = messages.mensaje response.replyMessage.forEach( async messages => {
if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')} var thisMsg = messages.mensaje
await sendMessage(client, from, remplazos(thisMsg, client), response.trigger); if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')}
await sendMessage(client, from, remplazos(thisMsg, client), response.trigger);
})
}, response.delay) }, response.delay)
} }
else{ else
/**
* Si quieres enviar un mensaje.
*/
{
// await sendMessage(client, from, nuevaRespuesta, response.trigger, step); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo. // await sendMessage(client, from, nuevaRespuesta, response.trigger, step); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo.
response.replyMessage.forEach( async messages => { response.replyMessage.forEach( async messages => {
var thisMsg = messages.mensaje var thisMsg = messages.mensaje
if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')} if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')}
await sendMessage(client, from, remplazos(thisMsg, client), response.trigger); await sendMessage(client, from, remplazos(thisMsg, client), response.trigger);
}) })
} }
/**
* Si quieres enviar botones o listas
*/
if(response.hasOwnProperty('actions')){ if(response.hasOwnProperty('actions')){
const { actions } = response; const { actions } = response;
// console.log("++++++++++++++++++++++++++++ SEND MESG BUTTON/LIST +++++++++++++++++++++++++++++++++++"); // console.log("++++++++++++++++++++++++++++ SEND MESG BUTTON/LIST +++++++++++++++++++++++++++++++++++");
if(actions['sections'] === undefined){ //Botones if(actions['sections'] === undefined){ //Botones
console.log("Botones") // console.log("Botones")
await sendMessageButton(client, from, null, actions); await sendMessageButton(client, from, null, actions);
} }
else{ //Listas else { //Listas
console.log("Listas") // console.log("Listas")
// console.log(actions)
await sendMessageList(client, from, null, actions); await sendMessageList(client, from, null, actions);
} }
} }
return return
} }
/** /**
* Regresa el mensaje enviado, con los remplazos procesados. * Si quieres tener un mensaje por defecto
*/ */
if(message.search('/rpt') > -1){
newBody = remplazos(newBody, client);
newBody = newBody.replace("/rpt ", "");
client.sendMessage(from, newBody);
return
}
/*
============================================================================
========================== ENVIO MASIVO TEST ===========================
============================================================================
*/
if(message=='/spam'){
const masivo = require('./spam.json')
var saludo;
var caritas;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function retardo() {
for (sp=0;sp<masivo.length;sp++) {
console.log(masivo[sp].numero+"@c.us");
var rnd = getRandomInt(1,7); // Random entre 1 y 6 segundos.
if(rnd==1||rnd==4){saludo = "Hola ";}
else if(rnd==2||rnd==5){saludo = "Saludos ";}
else {saludo = "%saludo% ";}
if(rnd==1){caritas = "👨🏻‍🦰👩🏻‍🦰";}
else if(rnd==2){caritas = "👩🏻‍🦰👨🏻‍🦰";}
else if(rnd==3){caritas = "🧔🏽👧🏽";}
else if(rnd==4){caritas = "👧🏽🧔🏽";}
else if(rnd==5){caritas = "👩🏻‍🦰🧔🏽";}
else if(rnd==6){caritas = "🧔🏽👩🏻‍🦰";}
if(sp % 15 === 0){console.log("******** VAN 15, HACEMOS PAUSA DE 10 SEGUNDOS ********"); await sleep(10000);} //
console.log(`============= Mandamos el mensaje ${sp} ==============`);
var elTextoDelMensaje = caritas + " *" + saludo + "amigo tendero* ❗❗👋🏻\n🕊 *GUNA* trae para ti dinámicas digitales, con las que podrás participar para ganar increíbles premios. 🏆💸💰\nSigue los siguientes pasos: 😃\n*1.* 📲Sigue la página de Yo Soy Guna en Facebook en la siguiente liga ➡️ https://www.facebook.com/yosoyguna\n*2.* 👉🏻Es importante des click en el botón Me Gusta 👍\n*3.* 🧐Sigue la dinámica que publicaremos , subiendo tu foto 📸 con los siguientes #yosoyguna #gunatenderos #gunachampions\n*4.* 🥳🎉En esta misma página , podrás ver publicados los ganadores🏅 y el tiempo en que serán elegidos. 💲 Además de tener acceso a increíbles promociones 🤑";
sendMedia(client, masivo[sp].numero+"@c.us", "envioMasivoGuna.jpg");
await sleep(500);
client.sendMessage(masivo[sp].numero+"@c.us", remplazos(elTextoDelMensaje, client));
// client.sendMessage(masivo[i].numero+"@c.us", "Este es un mensaje de prueba para *"+masivo[i].numero+"*, HORA:*"+new Date().toLocaleTimeString()+"*");
console.log(`Esperamos ${rnd} segundos...`);
await sleep(rnd*1000);
}
console.log('Done');
}
retardo();
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive
}
//Si quieres tener un mensaje por defecto
if (process.env.DEFAULT_MESSAGE === 'true') { if (process.env.DEFAULT_MESSAGE === 'true') {
const response = await responseMessages('DEFAULT') const response = await responseMessages('DEFAULT')
// await sendMessage(client, from, response.replyMessage, response.trigger); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo. // await sendMessage(client, from, response.replyMessage, response.trigger); // Mod by CHV - Para mandar varios mensajes en el mismo response, se cambio esta linea por el forEach de abajo.
@@ -297,26 +634,24 @@ const listenMessage = () => client.on('message', async msg => {
/** /**
* Si quieres enviar botones * Si quieres enviar botones
*/ */
if(response.hasOwnProperty('actions')){ // if(response.hasOwnProperty('actions')){
const { actions } = response; // const { actions } = response;
if(actions['sections'] === undefined){ //Botones // if(actions['sections'] === undefined){ //Botones
console.log("Botones") // console.log("Botones")
await sendMessageButton(client, from, null, actions); // await sendMessageButton(client, from, null, actions);
} // }
else{ //Listas // else{ //Listas
console.log("Listas") // console.log("Listas")
await sendMessageList(client, from, null, actions); // await sendMessageList(client, from, null, actions);
} // }
} // }
return return
} }
}); });
/** /**
* Este evento es necesario para el filtro de Dialogflow * Este evento es necesario para el filtro de Dialogflow
*/ */
const listenMessageFromBot = () => client.on('message_create', async botMsg => { const listenMessageFromBot = () => client.on('message_create', async botMsg => {
const { body } = botMsg; const { body } = botMsg;
const dialogflowFilterConfig = fs.readFileSync('./flow/dialogflow.json', 'utf8'); const dialogflowFilterConfig = fs.readFileSync('./flow/dialogflow.json', 'utf8');
@@ -334,34 +669,39 @@ const listenMessageFromBot = () => client.on('message_create', async botMsg => {
} }
}); });
client = new Client({ // ####################################################################################################################
// ############################## INICIAN FUNCIONES PARA LA CREACION DEL CLIENTE ####################################
// ############################## DE WHATSAPP-WEB.JS ####################################
// ####################################################################################################################
client = new Client({
authStrategy: new LocalAuth(), authStrategy: new LocalAuth(),
puppeteer: { headless: true, args: ['--no-sandbox','--disable-setuid-sandbox'] } puppeteer: { headless: true, args: ['--no-sandbox','--disable-setuid-sandbox'] }
}); });
client.on('qr', qr => generateImage(qr, () => { client.on('qr', qr => generateImage(qr, () => {
qrcode.generate(qr, { small: true }); qrcode.generate(qr, { small: true });
console.log(`Ver QR http://localhost:${port}/qr`) console.log(`Ver QR http://localhost:${port}/qr`)
socketEvents.sendQR(qr) socketEvents.sendQR(qr)
})) }))
client.on('ready', (a) => { client.on('ready', (a) => {
connectionReady() connectionReady()
listenMessage() listenMessage()
listenMessageFromBot() listenMessageFromBot()
// socketEvents.sendStatus(client) // socketEvents.sendStatus(client)
}); });
client.on('auth_failure', (e) => { client.on('auth_failure', (e) => {
// console.log(e) // console.log(e)
// connectionLost() // connectionLost()
}); });
client.on('authenticated', () => { client.on('authenticated', () => {
console.log('AUTHENTICATED'); console.log('AUTHENTICATED');
}); });
client.initialize(); client.initialize();
/** /**
* Verificamos si tienes un gesto de db * Verificamos si tienes un gesto de db
@@ -374,9 +714,32 @@ const listenMessageFromBot = () => client.on('message_create', async botMsg => {
server.listen(port, () => { server.listen(port, () => {
console.log(`El server esta listo en el puerto ${port}`); console.log(`El server esta listo en el puerto ${port}`);
}) })
checkEnvFile(); checkEnvFile();
// ####################################################################################################################
// ############################## INICIAN FUNCIONES VARIAS ####################################
// ####################################################################################################################
/**
* Regresa un número random entre los parametros min y max dados.
* @param {*} min
* @param {*} max
* @returns
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive
}
/**
* Revisa que exista el archivo "chats/numero.json"
* @param {*} theFile
* @returns
*/
function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el archivo "chats/numero.json" function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el archivo "chats/numero.json"
const fs = require('fs');
if (fs.existsSync(theFile)) { if (fs.existsSync(theFile)) {
// console.log("Si existe el archivo "+ theFile); // console.log("Si existe el archivo "+ theFile);
var h = true; var h = true;
@@ -394,6 +757,10 @@ function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el a
function traeMensajes(from){ //MOD by CHV - Agregamos para traer el historial de mensajes function traeMensajes(from){ //MOD by CHV - Agregamos para traer el historial de mensajes
var histlMsjs = {}; var histlMsjs = {};
var hayHistorial = (chkFile(`${__dirname}/chats/`+from+".json")); var hayHistorial = (chkFile(`${__dirname}/chats/`+from+".json"));
console.log(hayHistorial)
// var hayHistorialNoBlanks = hayHistorial.find(k => k.messages.message != "")
// console.log(hayHistorialNoBlanks)
// var {keywords} = stepsInitial.find(k => k.key.includes(key))
if(hayHistorial){ if(hayHistorial){
let rawdata = fs.readFileSync(`./chats/${from}.json`); let rawdata = fs.readFileSync(`./chats/${from}.json`);
let elHistorial = JSON.parse(rawdata); let elHistorial = JSON.parse(rawdata);
@@ -404,6 +771,10 @@ function traeMensajes(from){ //MOD by CHV - Agregamos para traer el historial de
// console.log("Mensajes:"+totalMsjs+", Ultimo:"+JSON.stringify(ultimoMensaje)); // console.log("Mensajes:"+totalMsjs+", Ultimo:"+JSON.stringify(ultimoMensaje));
// console.log("Anterior:"+JSON.stringify(mensajeAnterior)); // console.log("Anterior:"+JSON.stringify(mensajeAnterior));
} }
console.log(histlMsjs)
// var histlMsjsNoBlanks = histlMsjs.find(k => k.message != "")
var histlMsjsNoBlanks = histlMsjs.filter(x => x.message != "")
console.log(histlMsjsNoBlanks)
return histlMsjs; return histlMsjs;
} }

BIN
bot.xlsx Normal file

Binary file not shown.

View File

@@ -63,7 +63,7 @@ const sendMessage = async (client, number = null, text = null, trigger = null, r
number = cleanNumber(number) number = cleanNumber(number)
const message = text const message = text
client.sendMessage(number, message); client.sendMessage(number, message);
console.log(number, message, regla) // console.log(number, message, regla)
await readChat(number, message, trigger, regla) //MOD by CHV - Agregamos el parametro "regla" await readChat(number, message, trigger, regla) //MOD by CHV - Agregamos el parametro "regla"
console.log(`⚡⚡⚡ Enviando mensajes....`); console.log(`⚡⚡⚡ Enviando mensajes....`);
// console.log("********************* SEND MESSAGE **************************************"); // console.log("********************* SEND MESSAGE **************************************");

View File

@@ -86,5 +86,16 @@
{ {
"keywords": "*pak*3*|*pak*angular*|*paquete*3*|*paquete*angular*", "keywords": "*pak*3*|*pak*angular*|*paquete*3*|*paquete*angular*",
"key": "paq3" "key": "paq3"
},
{
"keywords": [
"/soporte",
"/ayuda"
],
"key": "soporte"
},
{
"keywords": "*",
"key": "Desbloqueo"
} }
] ]

View File

@@ -15,6 +15,7 @@
"trigger":null "trigger":null
}, },
"doblemensaje":{ "doblemensaje":{
"keywords": "7|*doble*mensaje*",
"replyMessage":[ "replyMessage":[
{"mensaje":["Este es un ejemplo del envío de *varios* mensajes con la *misma regla* en el *response.json*"]}, {"mensaje":["Este es un ejemplo del envío de *varios* mensajes con la *misma regla* en el *response.json*"]},
{ {
@@ -24,9 +25,11 @@
], ],
"media":null, "media":null,
"trigger":null, "trigger":null,
"goto":"menu" "goto":"menu",
"pasoRequerido":"menu"
}, },
"menu":{ "menu":{
"keywords": ["/menu"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -45,6 +48,7 @@
"trigger":null "trigger":null
}, },
"opcion1":{ "opcion1":{
"keywords": ["1"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -64,6 +68,7 @@
"goto":"menu" "goto":"menu"
}, },
"opcion2":{ "opcion2":{
"keywords": ["2"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -81,11 +86,12 @@
"goto":"menu" "goto":"menu"
}, },
"opcion3":{ "opcion3":{
"keywords": ["3"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
"Seleccionaste la *opción 3*\n", "Seleccionaste la *opción 3*\n",
"Por favor dame tu nombre.\n", "*Por favor dame tu nombre.*\n",
"Aquí vamos a aceptar *cualquier* texto, porque en el *initial.json* tenemos keywords : \"*\" (un asterisco en expresiones regulares quiere decir *\"cualquier cosa\"*)", "Aquí vamos a aceptar *cualquier* texto, porque en el *initial.json* tenemos keywords : \"*\" (un asterisco en expresiones regulares quiere decir *\"cualquier cosa\"*)",
"Y en *response.json* en la opción correspondiente tenemos \"pasoRequerido\" : \"menu\", que quiere decir que SOLO se va a disparar cuando el paso anterior sea \"menu\"." "Y en *response.json* en la opción correspondiente tenemos \"pasoRequerido\" : \"menu\", que quiere decir que SOLO se va a disparar cuando el paso anterior sea \"menu\"."
] ]
@@ -95,6 +101,7 @@
"pasoRequerido":"menu" "pasoRequerido":"menu"
}, },
"recibenombre":{ "recibenombre":{
"keywords": "*",
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -109,6 +116,7 @@
"goto":"menu" "goto":"menu"
}, },
"gRevisaCliente":{ "gRevisaCliente":{
"keywords": "*",
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -121,6 +129,7 @@
"pasoRequerido":"gallina" "pasoRequerido":"gallina"
}, },
"gGuardainfo":{ "gGuardainfo":{
"keywords": "*",
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -133,6 +142,7 @@
"pasoRequerido":"gRevisaCliente" "pasoRequerido":"gRevisaCliente"
}, },
"rnd":{ "rnd":{
"keywords": ["rnd"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[ "mensaje":[
@@ -150,6 +160,7 @@
"trigger":null "trigger":null
}, },
"rnd2":{ "rnd2":{
"keywords": ["rnd2"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":[""] "mensaje":[""]
@@ -169,6 +180,7 @@
} }
}, },
"lista":{ "lista":{
"keywords": ["4"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo%*, este es un ejemplo de listas"] "mensaje":["*%saludo%*, este es un ejemplo de listas"]
@@ -195,6 +207,7 @@
"goto":"menu" "goto":"menu"
}, },
"botones":{ "botones":{
"keywords": ["5"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo%*, este es un ejemplo de botones"] "mensaje":["*%saludo%*, este es un ejemplo de botones"]
@@ -216,6 +229,7 @@
"goto":"menu" "goto":"menu"
}, },
"cursos":{ "cursos":{
"keywords": ["cursos"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste *Cursos*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste *Cursos*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -226,6 +240,7 @@
"goto":"menu" "goto":"menu"
}, },
"youtube":{ "youtube":{
"keywords": ["youtube"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste *YouTube*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste *YouTube*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -236,6 +251,7 @@
"goto":"menu" "goto":"menu"
}, },
"telegram":{ "telegram":{
"keywords": ["telegram"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste *Telegram*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste *Telegram*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -246,6 +262,7 @@
"goto":"menu" "goto":"menu"
}, },
"manzana":{ "manzana":{
"keywords": ["manzana"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste *manzana*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste *manzana*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -256,6 +273,7 @@
"goto":"menu" "goto":"menu"
}, },
"mango":{ "mango":{
"keywords": ["mango"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste *mango*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste *mango*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -266,6 +284,7 @@
"goto":"menu" "goto":"menu"
}, },
"platano":{ "platano":{
"keywords": ["platano"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste *platano*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste *platano*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -276,6 +295,7 @@
"goto":"menu" "goto":"menu"
}, },
"paq3":{ "paq3":{
"keywords": "*pak*3*|*pak*angular*|*paquete*3*|*paquete*angular*",
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo% %primer_nombre%*, seleccionaste el *paquete 3 de Angular*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."] "mensaje":["*%saludo% %primer_nombre%*, seleccionaste el *paquete 3 de Angular*\n","Automáticamente el flujo se regresa al *menú*, asi que puedes poner nuevamente un número del 1 al 7 sin necesidad de volver a iniciar con */menu*."]
@@ -286,6 +306,7 @@
"goto":"menu" "goto":"menu"
}, },
"botonespaq3":{ "botonespaq3":{
"keywords": ["6"],
"replyMessage":[ "replyMessage":[
{ {
"mensaje":["*%saludo%*, este es un ejemplo de botones y regExp"] "mensaje":["*%saludo%*, este es un ejemplo de botones y regExp"]
@@ -305,5 +326,97 @@
}, },
"pasoRequerido":"menu", "pasoRequerido":"menu",
"goto":"menu" "goto":"menu"
},
"soporte":{
"keywords":["/soporte", "/ayuda"],
"replyMessage":[
{
"mensaje":[
"Bienvenido al soporte de Keymon, soy *Bow*.\n\n",
"Dame por favor el usuario que quieres desbloquear respetando *mayúsculas* y *minúsculas*."
]
}
],
"media":null,
"trigger":null
},
"Desbloqueo":{
"keywords": "*",
"replyMessage":[
"Mensaje de desbloqueo de usuarios."
],
"funcion":"desbloqueaUsuario",
"media":null,
"trigger":null,
"pasoRequerido":"soporte"
},
"gunaCats":{
"keywords": ["/guna", "/demoventa", "/demoguna", "⬅️ cambiar categoria"],
"replyMessage":[
"Mensaje de getGunaCats"
],
"funcion":"getGunaCats",
"media":null,
"trigger":null
},
"gunaCats2":{
"keywords": "*",
"replyMessage":[
"Mensaje de getGunaCats2"
],
"funcion":"getGunaSubtipo",
"media":null,
"trigger":null,
"pasoRequerido":"gunaCats"
},
"gunaProds":{
"keywords": "*",
"replyMessage":[
"Mensaje de getGunaCats2"
],
"funcion":"getGunaProds",
"media":null,
"trigger":null,
"pasoRequerido":"gunaCats2"
},
"gunaProdsAgrega":{
"keywords": "*",
"replyMessage":[
"Seleccionaste *%msjant_0%*, por favor indica la cantidad que quieres comprar (*solo el número*)."
],
"funcion":"agregaProds",
"media":null,
"trigger":null,
"pasoRequerido":"gunaProds"
},
"gunaProdsCantidad":{
"keywords": "*",
"replyMessage":[
"Recibi cantidad"
],
"funcion":"prodCantidad",
"media":null,
"trigger":null,
"pasoRequerido":"gunaProdsAgrega"
},
"gunaComprarMas":{
"keywords": "*agregar productos",
"replyMessage":[
"Quiero comprar mas."
],
"funcion":"comprarMas",
"media":null,
"trigger":null,
"pasoRequerido":"gunaProdsCantidad"
},
"gunaTerminaCompra":{
"keywords": "*terminar",
"replyMessage":[
"Termina la compra"
],
"funcion":"terminaCompra",
"media":null,
"trigger":null,
"pasoRequerido":"gunaProdsCantidad"
} }
} }

View File

@@ -0,0 +1,12 @@
{
"type": "service_account",
"project_id": "strong-maker-107118",
"private_key_id": "419c2f761213d11f2f30edab66832a9c475e1d33",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXlNkR2C9L7mXp\niMfPC4GwOKZcLIAa2XzrigJg3ettAHnWbxFSX4mS9AsmDKjBvkxpRVo+6gBzdtPa\nCZUQVZI6cWE+lCD2fMabwRQMosHxpRTUCruAnb/sku9y1o/KpdDemmqPaAHYxZXV\nex88svqcCPNhivqiPE/cRb1HoVu08IDG31Kgy3+iTpKQux05ngrYwem7wQl2k8dX\nS2SPp7YQID3gZeqWHyC2GVazn3Rz0PuKdp3wMnGB6MMI0yk3vLPHNpsEGyuyNeLG\nya68XBY86y9+LHZ8EwxUdVUmt8hUm0h5bDQftosRhgJakTUHZg9qNTM4iEJ7WYwP\nSao143C/AgMBAAECggEAI6kWxSm5HSWDdyot6cpR+sKhhjgYPW4XiLuCDDWkFsT6\n4nqUkhyFRylBBNttjkA6fI7BJbdojrEBIfKZf/kKYMorggICd94zrkULL3yRegr1\nfePZQ1EU6SnJxnnGkbN0cGDOWrLOMhDxFD4IcJknSmin9c0wYLt69wlpjNqcrw/B\ny6K63hi7M0iXGEHp8nz8Vf1l7VA82hCwUi7D73pkORH98xVY4+MYOTqrCvU0/O2m\nVqP5+mLMG/fPFlMnk8FgL3Q4dqiZ/ds7a6qXND5htSX0sFroINrTYiyXJ73OCgre\nlIbUuAD/92fuHKBdcIaaZvkEEAVTYlainm6LGroeSQKBgQDtq3mUTYO3998GiWO4\nVKnw7yC12WbwOaIDvlccWuTRWByJrRIJmsA1EXg18i9kf9AwxesbRT7xRBCwRMhs\nKUDbKaqvdf4BRARFWe0DSKQZIJpjCQsOtmOaV3yZP5uKLehQKPGgsIVT1A3XmIZW\nNzDAufVM5mjW8KbTNeBmMKRCJwKBgQDoNUMzDTLFl147jOaBJbq99Gd2pB7Aa8dY\n7SI3mXMMX0xCPU06Ym+wI485ybFllm+Bg018/+fJzli3Ko3nNuGcJplYzV8Z/eru\nMWGFCAXq3iWUiwXR9snmTAyO8uYXm7DnnhPxHNr8B3g3v55cTIqEjRn6YF5p7qBD\ntFQrV0ozqQKBgAvqqx/qew5AWWhkfyGA7TxtYQB9NBIbcaoqYwfC7vIoLtYgXWUp\n4zVF+PcLe6DYX8HySoWFhVBnj0anTD1QHDZg8nP1wJSjqmsnxSCDBedUoSkSDQHh\n10Cn3lF4xP26q4lJZEQgVa8MVN1YgnPUNJeVO11tuBf+3P5+FxBIpBPFAoGARxcH\nW7nOsW+GCfU5HJDQexc4FbppL7/PaAoxT5RLBJ6oWh8qZZV9XA+G6co15UQJHz1z\nm7E85SunPWxpxT+oEoY+rFEzrGFwazvy/ydVqHIaTz/AqGdFqJvfvGPgzZl8r2xV\n7ptG76HZzDd95AQK5EnOiji2rve/WPr8SciPjwECgYBf2SejOtRDWo6TOAQtEgvL\ngxU852DwuIW79U/+G2zrJ7qbbRzYCiHtsuaGOgzR5AfqN1+i4PWaJxdIKxymlv4w\nMs+swdsTZCn2/Rj4TndvEXr3OvfMtp0uN68rBNG+pNe1cwi+/+wx/E5ZC3QWxePt\nOwijAJ+obR377HMJOTTOTg==\n-----END PRIVATE KEY-----\n",
"client_email": "strong-maker-107118@appspot.gserviceaccount.com",
"client_id": "",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/strong-maker-107118%40appspot.gserviceaccount.com"
}

View File

@@ -0,0 +1,81 @@
const { getTime, getDate, getFormat, getCompareDate, getFormatMs } = require('util-tiempo')
const { GoogleSpreadsheet } = require('google-spreadsheet');
const fs = require('fs');
const RESPONSES_SHEET_ID = '1tVRX1ojXJadsjRUJ-pNv8DZgziaIMcAdsMtPmWQRBcM'; //Generar en google.cloud
const doc = new GoogleSpreadsheet(RESPONSES_SHEET_ID);
const CREDENTIALS = JSON.parse(fs.readFileSync('./implementaciones/credenciales.json'));
async function ingresarDatos(numero, mensaje){
let Fecha = getDate();
let Hora = getTime(Date.now(), {local: 'es-MX', timeZone: 'America/Mexico_City', hour12:false});
elNum = numero.replace('@c.us', '')
if(elNum.substring(0,3) == '521') { elNum = elNum.replace('521', '52') }
let rows = [{
Numero: elNum.trim(),
Mensaje: mensaje,
Fecha: Fecha,
Hora: Hora
}];
await doc.useServiceAccountAuth({
client_email: CREDENTIALS.client_email,
private_key: CREDENTIALS.private_key
});
await doc.loadInfo();
let sheet = doc.sheetsByTitle['Mensajes'];
// console.log("SHEET=", sheet)
for (let index = 0; index < rows.length; index++) {
const row = rows[index];
await sheet.addRow(row);
console.log("Datos guardados (sheets.js)")
}
// console.log('Fecha:',Fecha,);
// console.log('Hora:',Hora);
// console.log('Nombre:',nombre);
// console.log('Apellidos:',apellido);
// console.log('Direccion:',direccion);
// console.log('Planta:',planta);
// console.log('Codigo Postal:',CP);
// console.log('Descripcion:',descripcion);
// console.log('Telefono:',telsim);
// console.log('Horario deseado:',horario);
// console.log('ID_Solicitud: ',ID_Solicitud);
// console.log('Estado: ',Estado)
// console.log('-----------------------------------');
}
async function leerDatos(telsim){
await doc.useServiceAccountAuth({
client_email: CREDENTIALS.client_email,
private_key: CREDENTIALS.private_key
});
await doc.loadInfo();
let sheet = doc.sheetsByIndex[0];
let nya;
let cont = 0
let found = false
nya = [];
let rows = await sheet.getRows();
console.log(rows.length)
// for (let index = 0; index < rows.length; index++) {
// const row = rows[index];
// if (row.Telefono == telsim) {
// nya['Nombre'] = row.Nombre+' '+row.Apellido
// nya['Direccion'] = row.Direccion+' '+row.Planta+', '+row.CP
// nya['Estado'] = row.Estado
// }
// }
while (!found && cont < rows.length){ //Usamos while para que no recorra TODOS los registros y se pare encuanto lo encuentre.
const row = rows[cont];
console.log(row.Nombre, found, cont)
if (row.Telefono == telsim) {
nya['Nombre'] = row.Nombre+' '+row.Apellido
nya['Direccion'] = row.Direccion+', '+row.Planta+', CP:'+row.CP
nya['Estado'] = row.Estado
found = true
}
cont++
}
return nya
};
module.exports = {ingresarDatos,leerDatos};

218
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "test-ws-bot", "name": "chv-wweb-bot",
"version": "1.0.0", "version": "1.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "test-ws-bot", "name": "chv-wweb-bot",
"version": "1.0.0", "version": "1.0.1",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@google-cloud/dialogflow": "^5.2.0", "@google-cloud/dialogflow": "^5.2.0",
@@ -16,6 +16,7 @@
"exceljs": "^4.3.0", "exceljs": "^4.3.0",
"express": "^4.18.1", "express": "^4.18.1",
"file-type": "^17.1.6", "file-type": "^17.1.6",
"google-spreadsheet": "^3.3.0",
"googleapis": "^109.0.1", "googleapis": "^109.0.1",
"mime-db": "^1.52.0", "mime-db": "^1.52.0",
"moment": "^2.29.4", "moment": "^2.29.4",
@@ -25,7 +26,8 @@
"qrcode-terminal": "^0.12.0", "qrcode-terminal": "^0.12.0",
"socket.io": "^4.5.1", "socket.io": "^4.5.1",
"stormdb": "^0.6.0", "stormdb": "^0.6.0",
"whatsapp-web.js": "github:cheveguerra/whatsapp-web.js#WaWJS", "util-tiempo": "^1.0.41",
"whatsapp-web.js": "github:cheveguerra/whatsapp-web.js#WaWJS2",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
@@ -37,9 +39,9 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.20.7", "version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz",
"integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==",
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
}, },
@@ -576,9 +578,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.8.1", "version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -797,9 +799,9 @@
} }
}, },
"node_modules/ast-types/node_modules/tslib": { "node_modules/ast-types/node_modules/tslib": {
"version": "2.4.1", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
"dev": true "dev": true
}, },
"node_modules/async": { "node_modules/async": {
@@ -1246,9 +1248,9 @@
} }
}, },
"node_modules/content-type": { "node_modules/content-type": {
"version": "1.0.4", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@@ -1330,6 +1332,25 @@
"node-fetch": "2.6.7" "node-fetch": "2.6.7"
} }
}, },
"node_modules/cross-fetch/node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/culvert": { "node_modules/culvert": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz",
@@ -1526,9 +1547,9 @@
} }
}, },
"node_modules/engine.io-parser": { "node_modules/engine.io-parser": {
"version": "5.0.5", "version": "5.0.6",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.5.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz",
"integrity": "sha512-mjEyaa4zhuuRhaSLOdjEb57X0XPP9JEsnXI4E+ivhwT0GgzUogARx4MqoY1jQyB+4Bkz3BUOmzL7t9RMKmlG3g==", "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
} }
@@ -2162,9 +2183,9 @@
} }
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.1.3", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
"integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"has": "^1.0.3", "has": "^1.0.3",
@@ -2332,6 +2353,100 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/google-spreadsheet": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/google-spreadsheet/-/google-spreadsheet-3.3.0.tgz",
"integrity": "sha512-ahmRNh14s1i3phfvbF2mxen1lohWJpUaFWgsU6P6bXu7QrmxMaim1Ys/7BU4W5yucWCzphoIrHMbrbeIR5K9mw==",
"dependencies": {
"axios": "^0.21.4",
"google-auth-library": "^6.1.3",
"lodash": "^4.17.21"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/google-spreadsheet/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/google-spreadsheet/node_modules/gaxios": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz",
"integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==",
"dependencies": {
"abort-controller": "^3.0.0",
"extend": "^3.0.2",
"https-proxy-agent": "^5.0.0",
"is-stream": "^2.0.0",
"node-fetch": "^2.6.7"
},
"engines": {
"node": ">=10"
}
},
"node_modules/google-spreadsheet/node_modules/gcp-metadata": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz",
"integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==",
"dependencies": {
"gaxios": "^4.0.0",
"json-bigint": "^1.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/google-spreadsheet/node_modules/google-auth-library": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz",
"integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==",
"dependencies": {
"arrify": "^2.0.0",
"base64-js": "^1.3.0",
"ecdsa-sig-formatter": "^1.0.11",
"fast-text-encoding": "^1.0.0",
"gaxios": "^4.0.0",
"gcp-metadata": "^4.2.0",
"gtoken": "^5.0.4",
"jws": "^4.0.0",
"lru-cache": "^6.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/google-spreadsheet/node_modules/google-p12-pem": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz",
"integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==",
"dependencies": {
"node-forge": "^1.3.1"
},
"bin": {
"gp12-pem": "build/src/bin/gp12-pem.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/google-spreadsheet/node_modules/gtoken": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz",
"integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==",
"dependencies": {
"gaxios": "^4.0.0",
"google-p12-pem": "^3.1.3",
"jws": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/googleapis": { "node_modules/googleapis": {
"version": "109.0.1", "version": "109.0.1",
"resolved": "https://registry.npmjs.org/googleapis/-/googleapis-109.0.1.tgz", "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-109.0.1.tgz",
@@ -3030,9 +3145,9 @@
} }
}, },
"node_modules/marked": { "node_modules/marked": {
"version": "4.2.5", "version": "4.2.12",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz",
"integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==",
"bin": { "bin": {
"marked": "bin/marked.js" "marked": "bin/marked.js"
}, },
@@ -3255,9 +3370,9 @@
} }
}, },
"node_modules/node-fetch": { "node_modules/node-fetch": {
"version": "2.6.7", "version": "2.6.8",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==",
"dependencies": { "dependencies": {
"whatwg-url": "^5.0.0" "whatwg-url": "^5.0.0"
}, },
@@ -3330,9 +3445,9 @@
} }
}, },
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.2", "version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@@ -3908,9 +4023,9 @@
} }
}, },
"node_modules/protobufjs-cli/node_modules/glob": { "node_modules/protobufjs-cli/node_modules/glob": {
"version": "8.0.3", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"dependencies": { "dependencies": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
"inflight": "^1.0.4", "inflight": "^1.0.4",
@@ -3926,9 +4041,9 @@
} }
}, },
"node_modules/protobufjs-cli/node_modules/minimatch": { "node_modules/protobufjs-cli/node_modules/minimatch": {
"version": "5.1.2", "version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
}, },
@@ -4195,9 +4310,9 @@
} }
}, },
"node_modules/readdir-glob/node_modules/minimatch": { "node_modules/readdir-glob/node_modules/minimatch": {
"version": "5.1.2", "version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
}, },
@@ -4518,9 +4633,9 @@
"integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg=="
}, },
"node_modules/socket.io-parser": { "node_modules/socket.io-parser": {
"version": "4.2.1", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz",
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==",
"dependencies": { "dependencies": {
"@socket.io/component-emitter": "~3.1.0", "@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1" "debug": "~4.3.1"
@@ -4774,9 +4889,9 @@
} }
}, },
"node_modules/systeminformation": { "node_modules/systeminformation": {
"version": "5.17.1", "version": "5.17.7",
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.17.1.tgz", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.17.7.tgz",
"integrity": "sha512-NX/EjbKznOTgt2pfCzZb5bPj5YJOO9mCUrRXquGMtmlfs+BowVaMsJSUUCvqOm9wexx4/F+ng4JQp6I4sG+SyA==", "integrity": "sha512-0eQA5IkDlP4njQm9b5LvApCXaD52zFLfu+Xte1VdfaMChu4DxCSCmCjr/jAQK63gtHJ63x5gstCW5y3oWh9n+A==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"os": [ "os": [
@@ -5050,6 +5165,11 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
}, },
"node_modules/util-tiempo": {
"version": "1.0.41",
"resolved": "https://registry.npmjs.org/util-tiempo/-/util-tiempo-1.0.41.tgz",
"integrity": "sha512-HEesdZQpLY3S51xZ6hGbDvH8dVge+k+RnKJrb1mcME5UYXFeOaB7KQHA+sBiLsjls2Z0arseuxO2CZe9ZMCdug=="
},
"node_modules/utils-merge": { "node_modules/utils-merge": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -5120,8 +5240,8 @@
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
}, },
"node_modules/whatsapp-web.js": { "node_modules/whatsapp-web.js": {
"version": "1.18.4", "version": "1.19.2",
"resolved": "git+ssh://git@github.com/cheveguerra/whatsapp-web.js.git#b3e5d99f521c6d594fd2e204f12d3fd8ae4eba3b", "resolved": "git+ssh://git@github.com/cheveguerra/whatsapp-web.js.git#025f9914c3ee090c760fe6f2218e68b8bc9225af",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@pedroslopez/moduleraid": "^5.0.2", "@pedroslopez/moduleraid": "^5.0.2",

View File

@@ -18,6 +18,7 @@
"exceljs": "^4.3.0", "exceljs": "^4.3.0",
"express": "^4.18.1", "express": "^4.18.1",
"file-type": "^17.1.6", "file-type": "^17.1.6",
"google-spreadsheet": "^3.3.0",
"googleapis": "^109.0.1", "googleapis": "^109.0.1",
"mime-db": "^1.52.0", "mime-db": "^1.52.0",
"moment": "^2.29.4", "moment": "^2.29.4",
@@ -27,6 +28,7 @@
"qrcode-terminal": "^0.12.0", "qrcode-terminal": "^0.12.0",
"socket.io": "^4.5.1", "socket.io": "^4.5.1",
"stormdb": "^0.6.0", "stormdb": "^0.6.0",
"util-tiempo": "^1.0.41",
"whatsapp-web.js": "github:cheveguerra/whatsapp-web.js#WaWJS2", "whatsapp-web.js": "github:cheveguerra/whatsapp-web.js#WaWJS2",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },