From 1533161bbd01b90ce0d8578fb9d6e3eaba660594 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Sat, 15 Jan 2022 17:42:13 +0100 Subject: [PATCH] external downlaod --- .gitignore | 4 ++ adapter/index.js | 88 +++++++++++++++++++++++++++++++++++++++--- adapter/mysql.js | 27 ++++++++++--- app.js | 36 ++++++++--------- controllers/flows.js | 25 ++++++------ controllers/handle.js | 23 ++++++++++- controllers/save.js | 5 ++- controllers/send.js | 34 +++++++++------- media/undefined.jpeg | Bin 24542 -> 0 bytes 9 files changed, 180 insertions(+), 62 deletions(-) delete mode 100644 media/undefined.jpeg 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 8a1af44a3e2f4ba5800592e7157975cbdd52eed1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24542 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 U?|=b;Ku{9-BL2JKj4prw*$>BrB>(^b