From 9d293d3d6da741a07fd5c6e431e5a9292fad0785 Mon Sep 17 00:00:00 2001 From: cheveguerra Date: Sun, 5 Feb 2023 07:40:41 -0600 Subject: [PATCH 1/3] =?UTF-8?q?peque=C3=B1os=20camios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adapter/index.js | 13 ++-- app.js | 185 ++++++++++++++++++++++++++++----------------- flow/response.json | 14 +++- 3 files changed, 135 insertions(+), 77 deletions(-) diff --git a/adapter/index.js b/adapter/index.js index 0f0be4b..11c6a50 100644 --- a/adapter/index.js +++ b/adapter/index.js @@ -49,9 +49,10 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - */ if (process.env.DATABASE === 'none') { - + // console.log(message) var { key } = stepsInitial.find(k => k.keywords.includes(message)) || { key: null } - console.log("KEY="+key) + // console.log(stepsInitial) + // console.log("KEY="+key) /* ############################################### * REGEXP * #################################################### Si queremos usar RegExp, en los "keywords" de inital.json, en lugar de un arreglo usamos un string (quitamos los []) @@ -71,7 +72,7 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - 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(key == null && message.length > 0){ - var logRegEx = true + var logRegEx = false console.log("======= KEY ES NULO, USAMOS REGEXP ======="); for (i=0; i x.message != "") //Quitamos mensajes en blanco. var inicio = laLista[i].search('%msjant_'); var final = laLista[i].indexOf("%", inicio+1); var subStr = laLista[i].substring(inicio, final+1); diff --git a/app.js b/app.js index b044a26..a6863ff 100644 --- a/app.js +++ b/app.js @@ -31,7 +31,7 @@ app.use(express.json()) const MULTI_DEVICE = process.env.MULTI_DEVICE || 'true'; const server = require('http').Server(app) const port = process.env.PORT || 3000 - +const delay = (ms) => new Promise((resolve) => setTimeout(resolve,ms)) var client; var dialogflowFilter = false; var totalMsjs; //MOD by CHV - @@ -40,11 +40,12 @@ var newBody; //MOD by CHV - var nuevaRespuesta; //MOD by CHV - Se agrego para los remplazos var vars = [] app.use('/', require('./routes/web')) - - /** - * Escuchamos cuando entre un mensaje - */ -const listenMessage = () => client.on('message', async msg => { +let blackList = ['34692936038', '34678310819', '34660962689', '34649145761','34630283553','34648827637','34630255646','14178973313'] + +/** + * Escuchamos cuando entre un mensaje +*/ +listenMessage = () => client.on('message', async msg => { const { from, body, hasMedia } = msg; if (vars[from] === undefined) vars[from] = [] // console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); @@ -63,6 +64,12 @@ const listenMessage = () => client.on('message', async msg => { if (from === 'status@broadcast') { return } + + /** + * Blacklist, los telefonos inlcuidos en este arreglo son ignorados por el bot. + */ + console.log('BlackListed: ',blackList.includes(from.replace("@c.us",""))) + if (blackList.includes(from.replace("@c.us",""))) return message = newBody.toLowerCase(); const number = cleanNumber(from) client.theMsg['numero'] = number @@ -223,13 +230,13 @@ const listenMessage = () => client.on('message', async msg => { // console.log('RES=', RES) } } + /** * Llama el API para traer categorias de Guna. * @param {*} ctx El objeto del mensaje. */ async function getGunaCats(ctx) { - let par1 = ctx.theMsg.body - let theUrl = `http://localhost:8888/dbrquery?j={"query":"selectTipoFerreroMty","exec":"ExecuteQuery","params":{"par1":"${par1}"}}` + 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 client.on('message', async msg => { 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" @@ -327,7 +336,7 @@ const listenMessage = () => client.on('message', async msg => { rows: lasOpciones, } ], - `SUBCATEGORÍA ${body}`, + `SUBCATEGORÍA ${vars[from]['subtipo']}`, "Footer" ) client.sendMessage(from, productList) @@ -337,6 +346,7 @@ const listenMessage = () => client.on('message', async msg => { return error }); } + /** * Llama el API para traer productos de Guna. * @param {*} ctx El objeto del mensaje. @@ -345,20 +355,34 @@ const listenMessage = () => client.on('message', async msg => { // vars[from]['subtipo'] = ctx.theMsg.body if(vars[from]['prods'] === undefined) { vars[from]['prods'] = [] } let elProd = ctx.theMsg.body - 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'][elProd]) - let elMensaje = ctx.theMsg.replyMessage - let re = ctx.theMsg.body.trim().toLowerCase() - elMensaje = elMensaje.replace(re, elProd.toLowerCase()) + 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. @@ -366,33 +390,39 @@ const listenMessage = () => client.on('message', async msg => { async function prodCantidad(ctx) { // console.log("Entramos a prodCantidad") let laCant = ctx.theMsg.body.trim() - const reg = new RegExp('^[0-9]+$') - let elProd = remplazos("%msjant_2%").toLowerCase() + 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) - console.log("precio=", vars[from]['prods'][elProd]['precio']) vars[from]['prods'][elProd] = {"cant":laCant, "precio":vars[from]['prods'][elProd]['precio']} - console.log(vars[from]['prods']) - var elMensaje = "" - const prods = Object.keys(vars[from]['prods']); - prods.forEach((prod, index) => { - elMensaje = elMensaje + `${vars[from]['prods'][prod].cant} - ${prod[0].toUpperCase() + prod.substring(1)}\n` - console.log(`${prod}: ${vars[from]['prods'][prod]}`); - }); - elMensaje = elMensaje + "\n¿Quieres agregar mas productos a tu orden?" - // for(pr=0;pr { + 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":"Terminar"}, - {"body":"Agregar productos"} + {"body":"➕ Agregar productos"}, + {"body":"⬅️ Cambiar categoría"}, + {"body":"✖️ Terminar"} ] } sendMessageButton(client, from, "xxx", bts) @@ -412,11 +442,22 @@ const listenMessage = () => client.on('message', async msg => { 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 + } /** @@ -448,7 +489,7 @@ const listenMessage = () => client.on('message', async msg => { console.log("############# Encontramos función, ejecutamos la función '" + response.funcion + "'") laFuncion = response.funcion + "(client)" eval(laFuncion) - return + // return } if(response.hasOwnProperty('urlXXXXXXX') && response.hasOwnProperty('values')){ let theURL = response.url; @@ -568,35 +609,35 @@ if(message=='/spam'){ const masivo = require('./spam.json') var saludo; var caritas; - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + async function retardo() { + for (sp=0;sp k.messages.message != "") + // console.log(hayHistorialNoBlanks) + // var {keywords} = stepsInitial.find(k => k.key.includes(key)) if(hayHistorial){ let rawdata = fs.readFileSync(`./chats/${from}.json`); let elHistorial = JSON.parse(rawdata); @@ -755,6 +798,10 @@ function traeMensajes(from){ //MOD by CHV - Agregamos para traer el historial de // console.log("Mensajes:"+totalMsjs+", Ultimo:"+JSON.stringify(ultimoMensaje)); // 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; } diff --git a/flow/response.json b/flow/response.json index 6fb8226..eff337f 100644 --- a/flow/response.json +++ b/flow/response.json @@ -351,7 +351,7 @@ "pasoRequerido":"soporte" }, "gunaCats":{ - "keywords": ["/guna", "/demoventa", "/demoguna"], + "keywords": ["/guna", "/demoventa", "/demoguna", "⬅️ cambiar categoria"], "replyMessage":[ "Mensaje de getGunaCats" ], @@ -400,7 +400,7 @@ "pasoRequerido":"gunaProdsAgrega" }, "gunaComprarMas":{ - "keywords": ["Agregar productos"], + "keywords": "*agregar productos", "replyMessage":[ "Quiero comprar mas." ], @@ -408,5 +408,15 @@ "media":null, "trigger":null, "pasoRequerido":"gunaProdsCantidad" + }, + "gunaTerminaCompra":{ + "keywords": "*terminar", + "replyMessage":[ + "Termina la compra" + ], + "funcion":"terminaCompra", + "media":null, + "trigger":null, + "pasoRequerido":"gunaProdsCantidad" } } \ No newline at end of file From 693de00db8787c3d89e1143536994fd61da67a7e Mon Sep 17 00:00:00 2001 From: cheveguerra Date: Tue, 7 Feb 2023 00:09:24 -0600 Subject: [PATCH 2/3] fixes varios --- adapter/index.js | 127 +++++++++++--- app.js | 424 +++++++++++++++++++++------------------------ flow/response.json | 14 +- 3 files changed, 311 insertions(+), 254 deletions(-) diff --git a/adapter/index.js b/adapter/index.js index 11c6a50..592a81b 100644 --- a/adapter/index.js +++ b/adapter/index.js @@ -4,9 +4,7 @@ const { getDataIa } = require('./diaglogflow') // const stepsInitial = require('../flow/initial.json') const stepsReponse = require('../flow/response.json') const { isUndefined } = require('util'); -var msjsRecibidos = []; var ultimoStep; //MOD by CHV - -// var pasoAnterior = []; //MOD by CHV - Para guardar el paso anterior de cada número. (MOD - global en app.js) var pasoRequerido; //MOD by CHV - var _vamosA = ""; //MOD by CHV - var VA = ""; //MOD by CHV - @@ -45,14 +43,43 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - 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') { - // console.log(message) - var { key } = stepsInitial.find(k => k.keywords.includes(message)) || { key: null } - // console.log(stepsInitial) - // console.log("KEY="+key) + //******************************************************************************** */ + 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 new Promise((resolve, reject) => { //MOD by CHV - 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(key == null && message.length > 0){ + //******************************************************************************** */ var logRegEx = false + //******************************************************************************** */ console.log("======= KEY ES NULO, USAMOS REGEXP ======="); for (i=0; i new Promise((resolve, reject) => { //MOD by CHV - } else { if(logRegEx) console.log("--- NO CUMPLE PASO REQ"); - // console.log("pasoReq=" + resps[stepsInitial[i].key.toString()].pasoRequerido + " - PasoAnt=" + ultimoStep) } } } - // console.log("<<<<<<<<< "+key); + // console.log("<<<<<<<<< " + key); // cumplePasoRequerido(key) // ultimoPaso = pasoRequerido; // ultimoStep = key; @@ -135,7 +157,6 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - console.log("ASIGNAMOS _VAMOSA = " + _vamosA); pasoAnterior[elNum] = _vamosA; } - // console.log("ULTIMOSTEP="+ultimoStep) _vamosA = ""; // console.log("MESSAGE: "+message); // console.log("KEY: "+key); @@ -155,7 +176,7 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - 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') { let resData = { replyMessage: '', media: null, trigger: null } @@ -207,7 +228,7 @@ const saveMessage = ( message, trigger, number, regla ) => new Promise( async (r resolve( await saveMessageMysql( message, trigger, number ) ) break; 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) break; default: @@ -216,11 +237,12 @@ const saveMessage = ( message, trigger, number, regla ) => new Promise( async (r } }) -module.exports = { get, reply, getIA, saveMessage, remplazos, stepsInitial, vamosA } //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. + * 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. */ @@ -234,6 +256,7 @@ function vamosA (elNum, elPaso){ */ function remplazos(elTexto, extraInfo){ if(elTexto == null){elTexto = '';} + const fs = require('fs'); laLista = elTexto.toString().split(' '); // console.log(laLista); // console.log('============= remplazos ============'); @@ -390,8 +413,13 @@ function remplazos(elTexto, extraInfo){ 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" + const fs = require('fs'); if (fs.existsSync(theFile)) { // console.log("Si existe el archivo "+ theFile); var h = true; @@ -401,4 +429,59 @@ function chkFile(theFile){ //MOD by CHV - Agregamos para revisar que exista el a var h = false; } 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]); } \ No newline at end of file diff --git a/app.js b/app.js index a6863ff..bbd6120 100644 --- a/app.js +++ b/app.js @@ -11,19 +11,19 @@ const axios = require('axios').default;//MOD by CHV - Agregamos para el get del const qrcode = require('qrcode-terminal'); const { Client, LocalAuth, Buttons, List } = require('whatsapp-web.js'); 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 { connectionReady, connectionLost } = require('./controllers/connection') const { saveMedia, saveMediaToGoogleDrive } = require('./controllers/save') const { getMessages, responseMessages, bothResponse, waitFor } = require('./controllers/flows') const { sendMedia, sendMessage, lastTrigger, sendMessageButton, sendMessageList, readChat } = require('./controllers/send'); -const { remplazos, stepsInitial, vamosA } = require('./adapter/index');//MOD by CHV - Agregamos para utilizar remplazos y stepsInitial -const { isUndefined } = require('util'); -const { isSet } = require('util/types'); +const { remplazos, stepsInitial, vamosA, traeUltimaVisita } = require('./adapter/index');//MOD by CHV - Agregamos para utilizar remplazos y stepsInitial +// const { isUndefined } = require('util'); +// const { isSet } = require('util/types'); const { Console } = require('console'); -const { ClientRequest } = require('http'); +// const { ClientRequest } = require('http'); const { guardaXLSDatos, leeXLSDatos} = require('./Excel'); -const { ContextsClient } = require('@google-cloud/dialogflow'); +// const { ContextsClient } = require('@google-cloud/dialogflow'); const { ingresarDatos, leerDatos } = require('./implementaciones/sheets') const app = express(); app.use(cors()) @@ -34,7 +34,7 @@ const port = process.env.PORT || 3000 const delay = (ms) => new Promise((resolve) => setTimeout(resolve,ms)) var client; var dialogflowFilter = false; -var totalMsjs; //MOD by CHV - +// var totalMsjs; //MOD by CHV - // var vamosA = ""; //MOD by CHV - var newBody; //MOD by CHV - var nuevaRespuesta; //MOD by CHV - Se agrego para los remplazos @@ -48,41 +48,39 @@ let blackList = ['34692936038', '34678310819', '34660962689', '34649145761','346 listenMessage = () => client.on('message', async msg => { const { from, body, hasMedia } = msg; if (vars[from] === undefined) vars[from] = [] - // console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); console.log("+++++++++++++++++++++++++++++++++++++ INICIO +++++++++++++++++++++++++++++++++++++++"); - // console.log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); client.theMsg = msg; - // console.log("%%%%%%%%% userAgent = " + client?.options?.userAgent) console.log("HORA:"+new Date().toLocaleTimeString()+" FROM:"+from+", BODY:"+body+", HASMEDIA:"+hasMedia+", DEVICETYPE:"+client.theMsg?.deviceType); 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)){ return } // Este bug lo reporto Lucas Aldeco Brescia para evitar que se publiquen estados - if (from === 'status@broadcast') { - return - } - + if (from === 'status@broadcast') { return } /** - * Blacklist, los telefonos inlcuidos en este arreglo son ignorados por el bot. - */ - console.log('BlackListed: ',blackList.includes(from.replace("@c.us",""))) - if (blackList.includes(from.replace("@c.us",""))) 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(); const number = cleanNumber(from) client.theMsg['numero'] = number + // Guardamos el mensaje en Google Sheets ingresarDatos(from, body) - -// console.log(stepsInitial) + // console.log(stepsInitial) 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" client.theMsg['key'] = key - + /** * Guardamos el archivo multimedia que envia */ @@ -94,7 +92,6 @@ listenMessage = () => client.on('message', async msg => { /** * Si estas usando dialogflow solo manejamos una funcion todo es IA */ - if (process.env.DATABASE === 'dialogflow') { if (process.env.DIALOGFLOW_MEDIA_FOR_SLOT_FILLING === 'true' && dialogflowFilter) { waitFor(_ => hasMedia, 30000) @@ -123,6 +120,7 @@ listenMessage = () => client.on('message', async msg => { } if(body=='/listas'){ + // Asi se manda directamente con el ciente de whatsapp-web.js "client.sendMessage(from, productList)" const productList = new List( "Here's our list of products at 50% off", "View all products", @@ -139,96 +137,118 @@ listenMessage = () => client.on('message', async msg => { "Please select a product" ); console.log('##################################################################################################') - // console.log(from, lista) - // let sections = [{title:'sectionTitle',rows:[{id:'ListItem1', title: 'title1'},{id:'ListItem2', title:'title2'}]}]; - // let lista = new List('List body','btnText',sections,'Title','footer'); console.log("****************** productList ******************") console.log(productList) - client.sendMessage(from, productList); //cliente.sendMessage recibe el arreglo SIN nombres (solo las secciones los necesitan) - // client.sendMessage('5215527049036@c.us', productList); - // client.sendMessage('5215554192439@c.us', productList); - // await sendMessageList(client, '5215545815654@c.us', null, lista); //sendMessageList recibe el arreglo CON nombres, como viene del response.json - // await sendMessageList(client, '5215527049036@c.us', null, lista); - // await sendMessageList(client, '5215554192439@c.us', null, lista); - // client.sendMessage(from, lista); + client.sendMessage(from, productList); + // Asi se manda directamente con la funcion del bot. "sendMessageList(client, from, null, lista)" + // let sections = [ + // { title:'sectionTitle', + // rows:[ + // {id:'ListItem1', title: 'title1'}, + // {id:'ListItem2', title:'title2'} + // ] + // } + // ]; + // 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 * Aqui podemos ir agregando más pasos * a tu gusto! */ - - const lastStep = await lastTrigger(from) || null; - client.theMsg['lastStep'] = lastStep - // console.log("LAST STEP="+lastStep+", FROM:"+from); - if (lastStep) { - const response = await responseMessages(lastStep) - client.theMsg['trigger'] = response.trigger - console.log("CLIENT="+client+", FROM:"+from+", REPLYMESSAGE:"+response.replyMessage); - // 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. - response.replyMessage.forEach( async messages => { - var thisMsg = messages.mensaje - if(Array.isArray(messages.mensaje)){thisMsg = messages.mensaje.join('\n')} - await sendMessage(client, from, remplazos(thisMsg, client), response.trigger); - }) - } + // const lastStep = await lastTrigger(from) || null; + // client.theMsg['lastStep'] = lastStep + // // console.log("LAST STEP="+lastStep+", FROM:"+from); + // if (lastStep) { + // const response = await responseMessages(lastStep) + // client.theMsg['trigger'] = response.trigger + // console.log("CLIENT="+client+", FROM:"+from+", REPLYMESSAGE:"+response.replyMessage); + // // 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. + // response.replyMessage.forEach( async messages => { + // var thisMsg = messages.mensaje + // 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 */ - // const step = await getMessages(message, ); - // console.log("STEP - "+step+"|"+message); - // console.log("****** STEP="+step); - // console.log("****** MESSAGE:"+message); - const step = await getMessages(message, from); - client.theMsg['step'] = step - if (step) { - const response = await responseMessages(step); - client.theMsg['trigger'] = response.trigger - var resps = require('./flow/response.json'); - nuevaRespuesta = remplazos(resps[step].replyMessage.join(''), client); - client.theMsg['replyMessage'] = nuevaRespuesta - var pasoRequerido = resps[step].pasoRequerido; - // console.log('NUEVA RESPUESTA=', nuevaRespuesta) - - if(nuevaRespuesta.search("/URL")>-1){ - // Necesita instalado axios version 0.27.2 (npm i axios@0.27.2), si se instala una version mas nueva manda error de "GET no definido" o algo asi. - // console.log(theUrl); - console.log("========== GET URL ============"); - /* - ============================================================================ - ======================== DESBLOQUEO DE USUARIOS ========================== - ============================================================================ - */ - console.log('PASOREQUERIDO=', pasoRequerido) - if(pasoRequerido=="soporte"){ - // var theUrl=nuevaRespuesta.substring(5).replace("XXPARAM1XX",newBody); - // 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 - // // console.log('AXIOS RES=', response) - // }).catch(function (error) { - // console.log(error); - // return error - // }); - // console.log('RES=', RES) + const step = await getMessages(message, from); + client.theMsg['step'] = step + if (step) { + console.log("Entramos a STEP") + const response = await responseMessages(step); + client.theMsg['trigger'] = response.trigger + var resps = require('./flow/response.json'); + nuevaRespuesta = remplazos(resps[step].replyMessage.join(''), client); + client.theMsg['replyMessage'] = nuevaRespuesta + // var pasoRequerido = resps[step].pasoRequerido; + 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 setTimeout(resolve, ms)); + } + async function retardo() { + for (sp=0;sp client.on('message', async msg => { return } - /** * Llama el API para desbloquear un usuario. * @param {*} ctx El objeto del mensaje. @@ -482,6 +501,36 @@ listenMessage = () => client.on('message', async msg => { 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. */ @@ -491,25 +540,25 @@ listenMessage = () => client.on('message', async msg => { eval(laFuncion) // return } - if(response.hasOwnProperty('urlXXXXXXX') && 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 + 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. @@ -571,82 +620,9 @@ listenMessage = () => client.on('message', async msg => { return } - if(body=='trae'){ - const rows = await leeXLSDatos('x') - console.log("RESULTADOS:") - // d.forEach(row => async function() { - // console.log(row.nombre, row.edad, row.sexo) - // client.sendMessage(from, `Hola ${row.nombre}, recuerda que tienes un adeudo pendiente`) - // }) - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - async function retardo() { - for (sp=1;sp setTimeout(resolve, ms)); - } - async function retardo() { - for (sp=0;sp client.on('message_create', async botMsg => { } }); +// #################################################################################################################### +// ############################## INICIAN FUNCIONES PARA LA CREACION DEL CLIENTE #################################### +// ############################## DE WHATSAPP-WEB.JS #################################### +// #################################################################################################################### + client = new Client({ authStrategy: new LocalAuth(), puppeteer: { headless: true, args: ['--no-sandbox','--disable-setuid-sandbox'] } @@ -733,40 +715,32 @@ client.initialize(); server.listen(port, () => { console.log(`El server esta listo en el puerto ${port}`); }) + checkEnvFile(); - /** - * Llama el API para desbloquear el usuario. - * - * @param {*} theURL El URL para llamar al API - * @param {*} step +// #################################################################################################################### +// ############################## INICIAN FUNCIONES VARIAS #################################### +// #################################################################################################################### + +/** + * Regresa un número random entre los parametros min y max dados. + * @param {*} min + * @param {*} max + * @returns */ - 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 - }); - // const r = await axios.get(theUrl).then(function (response) { - // console.log('AXIOS RES=', response) - // }).catch(function (error) { - // console.log(error); - // return error - // }) - // return Promise.resolve(r) +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" + const fs = require('fs'); if (fs.existsSync(theFile)) { // console.log("Si existe el archivo "+ theFile); var h = true; diff --git a/flow/response.json b/flow/response.json index eff337f..f171a64 100644 --- a/flow/response.json +++ b/flow/response.json @@ -48,7 +48,7 @@ "trigger":null }, "opcion1":{ - "keywords": "1", + "keywords": ["1"], "replyMessage":[ { "mensaje":[ @@ -68,7 +68,7 @@ "goto":"menu" }, "opcion2":{ - "keywords": "2", + "keywords": ["2"], "replyMessage":[ { "mensaje":[ @@ -86,12 +86,12 @@ "goto":"menu" }, "opcion3":{ - "keywords": "3", + "keywords": ["3"], "replyMessage":[ { "mensaje":[ "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\"*)", "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\"." ] @@ -180,7 +180,7 @@ } }, "lista":{ - "keywords": "4", + "keywords": ["4"], "replyMessage":[ { "mensaje":["*%saludo%*, este es un ejemplo de listas"] @@ -207,7 +207,7 @@ "goto":"menu" }, "botones":{ - "keywords": "5", + "keywords": ["5"], "replyMessage":[ { "mensaje":["*%saludo%*, este es un ejemplo de botones"] @@ -306,7 +306,7 @@ "goto":"menu" }, "botonespaq3":{ - "keywords": "6", + "keywords": ["6"], "replyMessage":[ { "mensaje":["*%saludo%*, este es un ejemplo de botones y regExp"] From 26932ccefcd6da6ec23e86b30fe2bd06e055fc0b Mon Sep 17 00:00:00 2001 From: cheveguerra Date: Tue, 7 Feb 2023 02:01:49 -0600 Subject: [PATCH 3/3] format --- adapter/index.js | 32 +++++++++++++------------------- app.js | 17 ++++++++--------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/adapter/index.js b/adapter/index.js index 592a81b..7c4c84b 100644 --- a/adapter/index.js +++ b/adapter/index.js @@ -35,7 +35,6 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - elNum = num //MOD by CHV - 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"]) - // ultimoStep = siguientePaso.find(k => k.numero.includes(elNum))["va"] pasoAnterior[elNum] = siguientePaso.find(k => k.numero.includes(elNum))["va"] //Asignamos pasoAnterior al número. siguientePaso.splice(siguientePaso.indexOf(elNum), 1) console.log("******************** "+siguientePaso.find(k => k.numero.includes(elNum))) @@ -103,31 +102,30 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - var logRegEx = false //******************************************************************************** */ console.log("======= KEY ES NULO, USAMOS REGEXP ======="); - for (i=0; i -1){ + if(resps[stepsInitial[si].key].replyMessage.toString().search("/URL") > -1){ if(logRegEx) console.log("**************** HAY URL ****************") } break; @@ -151,16 +149,12 @@ const get = (message, num) => new Promise((resolve, reject) => { //MOD by CHV - if(resps[key]!=undefined){VA = resps[key].goto}else{VA=null} cumplePasoRequerido(key); _vamosA = VA; - console.log("cumplePasoPrevio[elNum]=", cumplePasoPrevio[elNum]) - + if(logRegEx) console.log("cumplePasoPrevio[elNum]=", cumplePasoPrevio[elNum], "_vamosA=", _vamosA) if(_vamosA != "" && _vamosA != undefined && cumplePasoPrevio[elNum] == true){ - console.log("ASIGNAMOS _VAMOSA = " + _vamosA); + if(logRegEx) console.log("ASIGNAMOS _VAMOSA = " + _vamosA); pasoAnterior[elNum] = _vamosA; } _vamosA = ""; - // console.log("MESSAGE: "+message); - // console.log("KEY: "+key); - // console.log("RESPONSE: "+response); if(cumplePasoPrevio[elNum]) {resolve(response);} } @@ -410,7 +404,7 @@ function remplazos(elTexto, extraInfo){ cumplePasoPrevio[elNum] = true; } pasoAnterior[elNum] = step - ultimoPaso = pasoRequerido; + // ultimoPaso = pasoRequerido; } /** diff --git a/app.js b/app.js index bbd6120..7f1c31d 100644 --- a/app.js +++ b/app.js @@ -179,7 +179,7 @@ listenMessage = () => client.on('message', async msg => { const step = await getMessages(message, from); client.theMsg['step'] = step if (step) { - console.log("Entramos a STEP") + // console.log("Entramos a STEP") const response = await responseMessages(step); client.theMsg['trigger'] = response.trigger var resps = require('./flow/response.json'); @@ -604,16 +604,15 @@ listenMessage = () => client.on('message', async msg => { /** * Si quieres enviar botones o listas */ - if(response.hasOwnProperty('actions')){ - const { actions } = response; - // console.log("++++++++++++++++++++++++++++ SEND MESG BUTTON/LIST +++++++++++++++++++++++++++++++++++"); - if(actions['sections'] === undefined){ //Botones - console.log("Botones") - await sendMessageButton(client, from, null, actions); + if(response.hasOwnProperty('actions')){ + const { actions } = response; + // console.log("++++++++++++++++++++++++++++ SEND MESG BUTTON/LIST +++++++++++++++++++++++++++++++++++"); + if(actions['sections'] === undefined){ //Botones + // console.log("Botones") + await sendMessageButton(client, from, null, actions); } else { //Listas - console.log("Listas") - // console.log(actions) + // console.log("Listas") await sendMessageList(client, from, null, actions); } }