diff --git a/README.md b/README.md index 2c7c14e..b34f647 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,13 @@ El siguiente proyecto se realizó con fines educativos para el canal de [Youtube | JSON File | ✅ | | QR Scan (route) | ✅ | | Easy deploy heroku | ✅ | +| Buttons | ✅ | | Add support ubuntu/linux | ✅ | +### (Nuevo) Botones + +[![btn](https://i.imgur.com/W7oYlSu.png)](https://youtu.be/5lEMCeWEJ8o) + ## Requisitos - node v14 o superior - VSCode (Editor de codigo) [Descargar](https://code.visualstudio.com/download) diff --git a/adapter/index.js b/adapter/index.js index e2786f7..944dcc0 100644 --- a/adapter/index.js +++ b/adapter/index.js @@ -32,7 +32,6 @@ const reply = (step) => new Promise((resolve, reject) => { if (process.env.DATABASE === 'none') { let resData = { replyMessage: '', media: null, trigger: null } const responseFind = stepsReponse[step] || {}; - console.log('Responder:',responseFind) resData = { ...resData, ...responseFind, diff --git a/app.js b/app.js index 53bac8c..6c81086 100644 --- a/app.js +++ b/app.js @@ -4,19 +4,37 @@ require('dotenv').config() const fs = require('fs'); const express = require('express'); +const cors = require('cors') const qrcode = require('qrcode-terminal'); const { Client } = require('whatsapp-web.js'); const mysqlConnection = require('./config/mysql') const { middlewareClient } = require('./middleware/client') -const { generateImage } = require('./controllers/handle') +const { generateImage, cleanNumber } = require('./controllers/handle') const { connectionReady, connectionLost } = require('./controllers/connection') const { saveMedia } = require('./controllers/save') const { getMessages, responseMessages, bothResponse } = require('./controllers/flows') -const { sendMedia, sendMessage, lastTrigger, sendMessageButton } = require('./controllers/send') - +const { sendMedia, sendMessage, lastTrigger, sendMessageButton, readChat } = require('./controllers/send') const app = express(); +app.use(cors()) app.use(express.json()) -app.use('/',require('./routes/web')) + +const server = require('http').Server(app) +const io = require('socket.io')(server, { + cors: { + origins: ['http://localhost:4200'] + } +}) + +let socketEvents = {sendQR:() => {} ,sendStatus:() => {}}; + +io.on('connection', (socket) => { + const CHANNEL = 'main-channel'; + socket.join(CHANNEL); + socketEvents = require('./controllers/socket')(socket) + console.log('Se conecto') +}) + +app.use('/', require('./routes/web')) const port = process.env.PORT || 3000 const SESSION_FILE_PATH = './session.json'; @@ -29,10 +47,13 @@ var sessionData; const listenMessage = () => client.on('message', async msg => { const { from, body, hasMedia } = msg; // Este bug lo reporto Lucas Aldeco Brescia para evitar que se publiquen estados - if(from === 'status@broadcast'){ - return + if (from === 'status@broadcast') { + return } message = body.toLowerCase(); + console.log('BODY',message) + const number = cleanNumber(from) + await readChat(number, message) /** * Guardamos el archivo multimedia que envia */ @@ -48,7 +69,7 @@ const listenMessage = () => client.on('message', async msg => { if (process.env.DATABASE === 'dialogflow') { const response = await bothResponse(message); await sendMessage(client, from, response.replyMessage); - if(response.media){ + if (response.media) { sendMedia(client, from, response.media); } return @@ -61,7 +82,7 @@ const listenMessage = () => client.on('message', async msg => { */ const lastStep = await lastTrigger(from) || null; - console.log({lastStep}) + console.log({ lastStep }) if (lastStep) { const response = await responseMessages(lastStep) await sendMessage(client, from, response.replyMessage); @@ -71,27 +92,36 @@ const listenMessage = () => client.on('message', async msg => { * Respondemos al primero paso si encuentra palabras clave */ const step = await getMessages(message); - console.log({step}) + console.log({ step }) + if (step) { const response = await responseMessages(step) await sendMessage(client, from, response.replyMessage, response.trigger); - // await sendMessageButton(client, from); - if(!response.delay && response.media){ + + if (!response.delay && response.media) { sendMedia(client, from, response.media); } - if(response.delay && response.media){ + if (response.delay && response.media) { setTimeout(() => { sendMedia(client, from, response.media); - },response.delay) + }, response.delay) } return } - if(process.env.DEFAULT_MESSAGE === 'true'){ - console.log('hehehe',(process.env.DEFAULT_MESSAGE) , step) + //Si quieres tener un mensaje por defecto + if (process.env.DEFAULT_MESSAGE === 'true') { const response = await responseMessages('DEFAULT') await sendMessage(client, from, response.replyMessage, response.trigger); + + /** + * Si quieres enviar botones + */ + if(response.hasOwnProperty('actions')){ + const { actions } = response; + await sendMessageButton(client, from, null, actions); + } return } }); @@ -112,11 +142,12 @@ const withSession = () => { ], } }); - + client.on('ready', () => { connectionReady() listenMessage() loadRoutes(client); + socketEvents.sendStatus() }); client.on('auth_failure', () => connectionLost()) @@ -141,12 +172,14 @@ const withOutSession = () => { client.on('qr', qr => generateImage(qr, () => { qrcode.generate(qr, { small: true }); console.log(`Ver QR http://localhost:${port}/qr`) + socketEvents.sendQR(qr) })) - - client.on('ready', () => { + + client.on('ready', (a) => { connectionReady() listenMessage() loadRoutes(client); + // socketEvents.sendStatus(client) }); client.on('auth_failure', () => connectionLost()); @@ -167,7 +200,7 @@ const withOutSession = () => { * Cargamos rutas de express */ - const loadRoutes = (client) => { +const loadRoutes = (client) => { app.use('/api/', middlewareClient(client), require('./routes/api')) } /** @@ -179,10 +212,12 @@ const withOutSession = () => { * Verificamos si tienes un gesto de db */ -if(process.env.DATABASE === 'mysql'){ +if (process.env.DATABASE === 'mysql') { mysqlConnection.connect() } -app.listen(port, () => { +server.listen(port, () => { console.log(`El server esta listo por el puerto ${port}`); -}) \ No newline at end of file +}) + + diff --git a/controllers/send.js b/controllers/send.js index 85c9b7e..cba01bb 100644 --- a/controllers/send.js +++ b/controllers/send.js @@ -36,14 +36,10 @@ const sendMessage = async (client, number = null, text = null, trigger = null) = * Enviamos un mensaje con buttons a nuestro cliente * @param {*} number */ -const sendMessageButton = async (client, number = null, text = null, trigger = null) => { +const sendMessageButton = async (client, number = null, text = null, actionButtons) => { number = cleanNumber(number) - const message = text - - let button = new Buttons("holaaaa", [ - { body: "Leer" }, - { body: "SIII" } - ], "ssssss", "foonooooter"); + const { title = null, message = null, footer = null, buttons = [] } = actionButtons; + let button = new Buttons(message,[...buttons], title, footer); client.sendMessage(number, button); console.log(`⚡⚡⚡ Enviando mensajes....`); @@ -77,7 +73,8 @@ const lastTrigger = (number) => new Promise((resolve, reject) => { * @param {*} message */ const readChat = async (number, message, trigger = null) => { - const pathExcel = `${__dirname}/../chats/${number}.xlsx`; + setTimeout(() => { + const pathExcel = `${__dirname}/../chats/${number}.xlsx`; const workbook = new ExcelJS.Workbook(); const today = moment().format('DD-MM-YYYY hh:mm') @@ -118,6 +115,7 @@ const readChat = async (number, message, trigger = null) => { console.log("err", err); }); } + }, 900) } -module.exports = { sendMessage, sendMedia, lastTrigger, sendMessageButton } \ No newline at end of file +module.exports = { sendMessage, sendMedia, lastTrigger, sendMessageButton, readChat } \ No newline at end of file diff --git a/controllers/socket.js b/controllers/socket.js new file mode 100644 index 0000000..05ff8d3 --- /dev/null +++ b/controllers/socket.js @@ -0,0 +1,16 @@ +module.exports = (socket) => { + return { + sendQR:(qr) => { + socket.emit('connection_qr',{ + qr + }) + }, + sendStatus:() => { + socket.emit('connection_status',{ + a:1 + }) + } + } + +} + diff --git a/flow/initial.json b/flow/initial.json index a5310ea..7b6b6b8 100644 --- a/flow/initial.json +++ b/flow/initial.json @@ -66,5 +66,23 @@ "vale gracias" ], "key": "STEP_4" + }, + { + "keywords": [ + "👉 Youtube" + ], + "key": "STEP_5" + }, + { + "keywords": [ + "😎 Cursos" + ], + "key": "STEP_6" + }, + { + "keywords": [ + "😁 Telegram" + ], + "key": "STEP_7" } ] \ No newline at end of file diff --git a/flow/response.json b/flow/response.json index 00e5466..92b518a 100644 --- a/flow/response.json +++ b/flow/response.json @@ -1,13 +1,21 @@ { "DEFAULT":{ "replyMessage":[ - "✌️ Bienvenido a este 🤖 CHATBOT de Whatsapp, lo primero \n", - "decirte que mi nombre es *Leifer Mendez*😎 \n", - "\n Si necesitas ver más info sobre las capacitacion tecnicas ", - "escribe *cursos* o *info*" + "🆗 Bienvenido a este 🤖 CHATBOT de Whatsapp, lo primero \n", + "decirte que mi nombre es *Leifer Mendez*😎 y te dejo opciones rapidas \n" ], "media":null, - "trigger":null + "trigger":null, + "actions":{ + "title":"¿Que te interesa ver?", + "message":"Recuerda todo este contenido es gratis y estaria genial que me siguas!", + "footer":"Gracias", + "buttons":[ + {"body":"😎 Cursos"}, + {"body":"👉 Youtube"}, + {"body":"😁 Telegram"} + ] + } }, "STEP_0":{ "replyMessage":[ @@ -95,5 +103,33 @@ ], "media":"https://media4.giphy.com/media/hur0SFIU5SH4mxNBWa/giphy.gif", "trigger":null + }, + "STEP_5":{ + "replyMessage":[ + "Muy bien te comparto el canal de Youtube \n" + ], + "media":"https://youtube.com/leifermendez", + "trigger":null + }, + "STEP_6":{ + "replyMessage":[ + "Perfecto, te voy a pasar la lista ", + "de los temas que tengo y un breve video 🙂🤖 \n\n", + "*Angular* Basico (Pago) \n", + "*Angular* Basico (Gratis) \n", + "*Node* Basico (Gratis) \n", + "*NGRX* Basico (Gratis) \n", + "*AWS* Basico (Pago) \n\n", + "Escribe la palabra del tema que te interese \n" + ], + "media":"https://i.giphy.com/media/5J5gN0WUk0VToHaK2p/giphy-downsized.gif", + "trigger":null + }, + "STEP_7":{ + "replyMessage":[ + "Vente al telegram \n" + ], + "media":"https://t.me/leifermendez", + "trigger":null } } \ No newline at end of file diff --git a/package.json b/package.json index 5c25f47..1168b87 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "license": "ISC", "dependencies": { "@google-cloud/dialogflow": "^4.6.0", + "cors": "^2.8.5", "dotenv": "^11.0.0", "exceljs": "^4.3.0", "express": "^4.17.2",