diff --git a/.gitignore b/.gitignore index 796233b..8ddf74a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,8 @@ session.json chats/* !chats/.gitkeep +media/* +!media/.gitkeep +mediaSend/* +!mediaSend/.gitkeep .env \ No newline at end of file diff --git a/adapter/index.js b/adapter/index.js index b90f607..66df0cb 100644 --- a/adapter/index.js +++ b/adapter/index.js @@ -1,12 +1,90 @@ -const {getData} = require('./mysql') +const {getData , getReply} = require('./mysql') -const get = (step) => new Promise((resolve, reject) => { +const get = (message) => new Promise((resolve, reject) => { + /** + * Si no estas usando un gesto de base de datos + */ + + if(process.env.DATABASE === 'none'){ + + const steps = [ + { + keywords:['hola','hi','buen dia'], + key:'STEP_1' + }, + { + keywords:['enviar pdf','pdf','enviarpdf'], + key:'STEP_2' + } + ] + + const {key} = steps.find(k => k.keywords.includes(message)) || {key:null} + const response = key || null + resolve(response) + } + /** + * Si usas MYSQL + */ if(process.env.DATABASE === 'mysql'){ - getData(step,(dt) => { - console.log('--->datos--',dt) + getData(message,(dt) => { resolve(dt) }); } }) -module.exports = {get} \ No newline at end of file + +const reply = (step) => new Promise((resolve, reject) => { + /** + * Si no estas usando un gesto de base de datos + */ + if(process.env.DATABASE === 'none'){ + let replyMessage = null; + let resData = {replyMessage:'', media:null, trigger:null} + switch(step){ + + case 'STEP_1': + replyMessage = [ + '✌️ Bienveido a este CHATBOT lo primero \n', + 'Decirte que mi nombre es Leifer Mendez \n\n', + '¿Quieres que te envie mi presentación? \n', + '*enviar pdf* o *omitir* \n', + ].join(''); + resData = {replyMessage, media:null} + resolve(resData); + return + break; + case 'STEP_2': + replyMessage = [ + 'Yeah! 😎 \n', + 'enviando...👌' + ].join(''); + resData = {replyMessage, media:'meme-1.png',trigger:'STEP_0'} + resolve(resData); + return + break; + case 'STEP_0': + replyMessage = [ + 'El flujo ha finalizado \n', + 'pero puedes ver todo el codigo de este \n', + 'repositorio en https://github.com/leifermendez/bot-whatsapp.git' + ].join(''); + resData = {replyMessage, media: null} + resolve(resData); + return + break; + + } + } + /** + * Si usas MYSQL + */ + if(process.env.DATABASE === 'mysql'){ + let resData = {replyMessage:'', media:null, trigger:null} + getReply(step,(dt) => { + resData = {...resData,...dt} + resolve(resData) + }); + } +}) + +module.exports = {get, reply} \ No newline at end of file diff --git a/adapter/mysql.js b/adapter/mysql.js index 9644ff4..dcaaefc 100644 --- a/adapter/mysql.js +++ b/adapter/mysql.js @@ -1,9 +1,26 @@ const {connection} = require('../config/mysql') -const getData = (option_key = '', callback) => connection.query(`SELECT * FROM db_test.keywords WHERE option_key = '${option_key}' LIMIT 1`,(error, results, fields) => { +getData = (message = '', callback) => connection.query( + `SELECT * FROM db_test.keywords WHERE value LIKE '%${message}%' LIMIT 1`, + (error, results + ) => { const [response] = results - let parseResponse = response?.value || ''; - parseResponse = parseResponse.split(',') || [] - callback(parseResponse) + const key = response?.option_key || null + callback(key) }); -module.exports = {getData} \ No newline at end of file + + +getReply = (option_key = '', callback) => connection.query( + `SELECT * FROM db_test.replies WHERE option_key = '${option_key}' LIMIT 1`, + (error, results + ) => { + const [response] = results + const value = { + replyMessage:response?.value || '', + trigger:response?.trigger || '', + media:response?.media || '' + } + callback(value) +}); + +module.exports = {getData, getReply} \ No newline at end of file diff --git a/app.js b/app.js index a596764..aa70d6f 100644 --- a/app.js +++ b/app.js @@ -46,33 +46,29 @@ const listenMessage = () => client.on('message', async msg => { */ const lastStep = await lastTrigger(from) || null; - - if (lastStep === 'STEP_2') { - const response = responseMessages(lastStep) - sendMessage(client, from, response); - return - } - - if (lastStep === 'STEP_3') { - const response = responseMessages(lastStep) - sendMessage(client, from, response); - return + if (lastStep) { + const response = await responseMessages(lastStep) + await sendMessage(client, from, response.replyMessage); } /** * Respondemos al primero paso si encuentra palabras clave */ - if (await getMessages('STEP_1', message)) { - const response = responseMessages('STEP_1') - sendMessage(client, from, response, 'STEP_2'); + const step = await getMessages(message); + if (step) { + const response = await responseMessages(step) + await sendMessage(client, from, response.replyMessage, response.trigger); + + if(!response.delay && response.media){ + sendMedia(client, from, response.media); + } + if(response.delay && response.media){ + setTimeout(() => { + sendMedia(client, from, response.media); + },response.delay) + } return } - - // if (getMessages('STEP_2').includes(message)) { - // const response = responseMessages('STEP_2') - // sendMessage(client, from, response); - // return - // } }); /** diff --git a/controllers/flows.js b/controllers/flows.js index 2a28331..4e0e1d7 100644 --- a/controllers/flows.js +++ b/controllers/flows.js @@ -1,21 +1,18 @@ -const {get} = require('../adapter') +const {get, reply} = require('../adapter') +const {saveExternalFile} = require('./handle') -const getMessages = async (step, message) => { - const data = await get(step) - return data.includes(message) +const getMessages = async (message) => { + const data = await get(message) + return data } - -const responseMessages = (step) => { - switch (step) { - case 'STEP_1': - return ['Si como estas', '🤔'].join('') - break; - case 'STEP_2': - return ['pa como estas', '🤔'].join('') - break; +const responseMessages = async (step) => { + const data = await reply(step) + if(data && data.media){ + const file = await saveExternalFile(data.media) + return {...data,...{media:file}} } - return null + return data } module.exports = { getMessages, responseMessages } \ No newline at end of file diff --git a/controllers/handle.js b/controllers/handle.js index ef373bd..1ef6c69 100644 --- a/controllers/handle.js +++ b/controllers/handle.js @@ -1,7 +1,28 @@ +const http = require('http'); // or 'https' for https:// URLs +const https = require('https'); // or 'https' for https:// URLs +const fs = require('fs'); + + const cleanNumber = (number) => { number = number.replace('@c.us', ''); number = `${number}@c.us`; return number } -module.exports = {cleanNumber} \ No newline at end of file +const saveExternalFile = (url) => new Promise((resolve, reject) => { + const ext = url.split('.').pop() + const checkProtocol = url.split('/').includes('https:'); + console.log(checkProtocol) + const handleHttp = checkProtocol ? https : http; + const name = `${Date.now()}.${ext}`; + const file = fs.createWriteStream(`./mediaSend/${name}`); + const request = handleHttp.get(url, function(response) { + const ext = response.headers['content-type'].split('/').pop() + response.pipe(file); + file.on('finish', function() { + file.close(); // close() is async, call cb after close completes. + resolve(name) + }); + }); +}) +module.exports = {cleanNumber, saveExternalFile} \ No newline at end of file diff --git a/controllers/save.js b/controllers/save.js index 1c53e2b..92555e0 100644 --- a/controllers/save.js +++ b/controllers/save.js @@ -1,4 +1,5 @@ const mimeDb = require('mime-db') +const fs = require('fs') /** * Guardamos archivos multimedia que nuestro cliente nos envie! @@ -6,10 +7,10 @@ const mimeDb = require('mime-db') */ -const saveMedia = () => { +const saveMedia = (media) => { const extensionProcess = mimeDb[media.mimetype] const ext = extensionProcess.extensions[0] - fs.writeFile(`../media/${media.filename}.${ext}`, media.data, { encoding: 'base64' }, function (err) { + fs.writeFile(`./media/${Date.now()}.${ext}`, media.data, { encoding: 'base64' }, function (err) { console.log('** Archivo Media Guardado **'); }); } diff --git a/controllers/send.js b/controllers/send.js index 023a81d..f8353ef 100644 --- a/controllers/send.js +++ b/controllers/send.js @@ -4,6 +4,7 @@ const moment = require('moment'); const fs = require('fs'); const { MessageMedia } = require('whatsapp-web.js'); const { cleanNumber } = require('./handle') +const { saveMedia } = require('../controllers/save') /** * Enviamos archivos multimedia a nuestro cliente * @param {*} number @@ -11,20 +12,24 @@ const { cleanNumber } = require('./handle') */ const sendMedia = (client, number, fileName) => { + const dirMedia = `${__dirname}/../mediaSend/${fileName}`; + console.log(dirMedia) number = cleanNumber(number) - const media = MessageMedia.fromFilePath(`${__dirname}/../mediaSend/${fileName}`); - client.sendMessage(number, media); + if(fs.existsSync(dirMedia)){ + const media = MessageMedia.fromFilePath(dirMedia); + client.sendMessage(number, media); + } } /** * Enviamos un mensaje simple (texto) a nuestro cliente * @param {*} number */ -const sendMessage = (client, number = null, text = null, trigger = null) => { +const sendMessage = async (client, number = null, text = null, trigger = null) => { number = cleanNumber(number) const message = text client.sendMessage(number, message); - readChat(number, message, trigger) + await readChat(number, message, trigger) console.log(`⚡⚡⚡ Enviando mensajes....`); } @@ -35,17 +40,16 @@ const lastTrigger = (number) => new Promise((resolve, reject) => { number = cleanNumber(number) const pathExcel = `${__dirname}/../chats/${number}.xlsx`; const workbook = new ExcelJS.Workbook(); - if(fs.existsSync(pathExcel)) - { + if (fs.existsSync(pathExcel)) { workbook.xlsx.readFile(pathExcel) - .then(() => { - const worksheet = workbook.getWorksheet(1); - const lastRow = worksheet.lastRow; - const getRowPrevStep = worksheet.getRow(lastRow.number); - const lastStep = getRowPrevStep.getCell('C').value; - resolve(lastStep) - }); - }else{ + .then(() => { + const worksheet = workbook.getWorksheet(1); + const lastRow = worksheet.lastRow; + const getRowPrevStep = worksheet.getRow(lastRow.number); + const lastStep = getRowPrevStep.getCell('C').value; + resolve(lastStep) + }); + } else { resolve(null) } }) @@ -55,7 +59,7 @@ const lastTrigger = (number) => new Promise((resolve, reject) => { * @param {*} number * @param {*} message */ - const readChat = async (number, message, trigger = null) => { +const readChat = async (number, message, trigger = null) => { const pathExcel = `${__dirname}/../chats/${number}.xlsx`; const workbook = new ExcelJS.Workbook(); const today = moment().format('DD-MM-YYYY hh:mm') diff --git a/media/undefined.jpeg b/media/undefined.jpeg deleted file mode 100644 index 8a1af44..0000000 Binary files a/media/undefined.jpeg and /dev/null differ