From ef61a8a0819db75b86e54bdef7a945787f4acc27 Mon Sep 17 00:00:00 2001 From: Enrique Date: Mon, 4 Sep 2023 17:55:50 -0500 Subject: [PATCH 1/5] sticker,image,video to _event_media --- packages/provider/src/meta/server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/provider/src/meta/server.js b/packages/provider/src/meta/server.js index a295f778a..9b72e2728 100644 --- a/packages/provider/src/meta/server.js +++ b/packages/provider/src/meta/server.js @@ -61,7 +61,7 @@ class MetaWebHookServer extends EventEmitter { } if (message.type === 'image') { - const body = generateRefprovider('_event_image_') + const body = generateRefprovider('_event_media_') const idUrl = message.image?.id const resolvedUrl = await getMediaUrl(this.version, idUrl, this.numberId, this.jwtToken) const responseObj = { @@ -91,7 +91,7 @@ class MetaWebHookServer extends EventEmitter { } if (message.type === 'video') { - const body = generateRefprovider('_event_video_') + const body = generateRefprovider('_event_media_') const idUrl = message.video?.id const resolvedUrl = await getMediaUrl(this.version, idUrl, this.numberId, this.jwtToken) @@ -138,7 +138,7 @@ class MetaWebHookServer extends EventEmitter { } if (message.type === 'sticker') { - const body = generateRefprovider('_event_sticker_') + const body = generateRefprovider('_event_media_') const responseObj = { type: message.type, From 8391037ff120265faeaa7277918b856d94294ff7 Mon Sep 17 00:00:00 2001 From: MartnReus Date: Wed, 6 Sep 2023 10:42:56 -0300 Subject: [PATCH 2/5] fix(database): MySQL conection timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ahora al momento de recibir un mensaje se comprueba el estado de la conexión con la base de datos MySQL. En el caso en que se haya desconectado, se llama de nuevo a la función que realiza la conexión. --- packages/database/src/mysql/index.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/database/src/mysql/index.js b/packages/database/src/mysql/index.js index e2836d1d0..09b1d6430 100644 --- a/packages/database/src/mysql/index.js +++ b/packages/database/src/mysql/index.js @@ -25,25 +25,27 @@ class MyslAdapter { }) } - getPrevByNumber = (from) => - new Promise((resolve, reject) => { - const sql = `SELECT * FROM history WHERE phone='${from}' ORDER BY id DESC` + getPrevByNumber = async (from) => { + if (this.db._closing) await this.init() + return await new Promise((resolve, reject) => { + const sql = `SELECT * FROM history WHERE phone='${from}' ORDER BY id DESC`; this.db.query(sql, (error, rows) => { if (error) { - reject(error) + reject(error); } if (rows.length) { - const [row] = rows - row.options = JSON.parse(row.options) - resolve(row) + const [row] = rows; + row.options = JSON.parse(row.options); + resolve(row); } if (!rows.length) { - resolve(null) + resolve(null); } - }) + }); }) + } save = (ctx) => { const values = [ From c99ab6c6ea5a69790b3229a9700fea1a0d45d222 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Thu, 7 Sep 2023 11:03:09 +0200 Subject: [PATCH 3/5] feat(provider): :fire: add tmp file twilio --- packages/provider/package.json | 2 +- packages/provider/src/twilio/index.js | 23 ++++++++++++++++++++++- packages/provider/src/twilio/server.js | 25 ++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/provider/package.json b/packages/provider/package.json index 84e96d4d1..48b0881d2 100644 --- a/packages/provider/package.json +++ b/packages/provider/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/provider", - "version": "0.0.124-alpha.0", + "version": "0.0.132-alpha.0", "description": "Esto es el conector a Twilio, Meta, etc...", "main": "./lib/mock/index.cjs", "keywords": [], diff --git a/packages/provider/src/twilio/index.js b/packages/provider/src/twilio/index.js index f51264a20..e19d2c932 100644 --- a/packages/provider/src/twilio/index.js +++ b/packages/provider/src/twilio/index.js @@ -20,8 +20,10 @@ class TwilioProvider extends ProviderClass { twilioHook vendor vendorNumber - constructor({ accountSid, authToken, vendorNumber, port = PORT }) { + publicUrl + constructor({ accountSid, authToken, vendorNumber, port = PORT, publicUrl = '' }) { super() + this.publicUrl = publicUrl this.vendor = new twilio(accountSid, authToken) this.twilioHook = new TwilioWebHookServer(port) this.vendorNumber = parseNumber(vendorNumber) @@ -66,6 +68,25 @@ class TwilioProvider extends ProviderClass { */ sendMedia = async (number, message, mediaInput = null) => { if (!mediaInput) throw new Error(`MEDIA_INPUT_NULL_: ${mediaInput}`) + const urlEncode = `${this.publicUrl}/tmp?path=${encodeURIComponent(mediaInput)}` + const regexUrl = /^(?!https?:\/\/)[^\s]+$/ + + const urlNotice = [ + `[NOTA]: Estas intentando enviar una fichero que esta en local.`, + `[NOTA]: Para que esto funcione con Twilio necesitas que el fichero este en una URL publica`, + `[NOTA]: más informacion aqui https://bot-whatsapp.netlify.app/docs/provider-twilio/`, + ].join('\n') + + if ( + mediaInput.includes('localhost') || + mediaInput.includes('127.0.0.1') || + mediaInput.includes('0.0.0.0') || + regexUrl.test(mediaInput) + ) { + console.log(urlNotice) + mediaInput = urlEncode + } + number = parseNumber(number) return this.vendor.messages.create({ mediaUrl: [`${mediaInput}`], diff --git a/packages/provider/src/twilio/server.js b/packages/provider/src/twilio/server.js index aaf49c256..2080bbe86 100644 --- a/packages/provider/src/twilio/server.js +++ b/packages/provider/src/twilio/server.js @@ -1,6 +1,8 @@ const { EventEmitter } = require('node:events') +const { existsSync, createReadStream } = require('node:fs') +const mime = require('mime-types') const polka = require('polka') -const { urlencoded } = require('body-parser') +const { urlencoded, json } = require('body-parser') const { parseNumber } = require('./utils') /** @@ -33,6 +35,25 @@ class TwilioWebHookServer extends EventEmitter { res.end(json) } + /** + * Manejar los local media como + * C\\Projects\\bot-restaurante\\tmp\\menu.png + * para que puedas ser llevar a una url online + * @param {*} req + * @param {*} res + */ + handlerLocalMedia = (req, res) => { + const { query } = req + const file = query?.path + if (!file) return res.end(`path: invalid`) + const decodeFile = decodeURIComponent(file) + if (!existsSync(decodeFile)) return res.end(`not exits: ${decodeFile}`) + const fileStream = createReadStream(decodeFile) + const mimeType = mime.lookup(decodeFile) + res.writeHead(200, { 'Content-Type': mimeType }) + fileStream.pipe(res) + } + /** * Contruir HTTP Server * @returns @@ -40,7 +61,9 @@ class TwilioWebHookServer extends EventEmitter { buildHTTPServer = () => { return polka() .use(urlencoded({ extended: true })) + .use(json()) .post('/twilio-hook', this.incomingMsg) + .get('/tmp', this.handlerLocalMedia) } /** From 589f96efc26d03d622c85619656757f3dfb8c39e Mon Sep 17 00:00:00 2001 From: "Binho.dev" Date: Wed, 13 Sep 2023 11:58:49 -0300 Subject: [PATCH 4/5] feat(bot): :sparkles: feat IdleState - Set a idle time to wait a user answer, after this send a auto message of inactivity No have breaking changes --- packages/bot/context/idleState.class.js | 54 +++++++++++++++++++++++++ packages/bot/core/core.class.js | 3 ++ 2 files changed, 57 insertions(+) create mode 100755 packages/bot/context/idleState.class.js diff --git a/packages/bot/context/idleState.class.js b/packages/bot/context/idleState.class.js new file mode 100755 index 000000000..aa51c9fc4 --- /dev/null +++ b/packages/bot/context/idleState.class.js @@ -0,0 +1,54 @@ +const { EventEmitter } = require('node:events') + +class IdleState extends EventEmitter { + timer = null + startTime = 0 + endTime = 0 + + setIdleTime = (timeInSeconds) => { + this.startTime = timeInSeconds + return this.reset() + } + + startTimer = () => { + this.timer = setInterval(() => { + const currentTime = new Date().getTime() + + if (currentTime > this.endTime) { + this.stop() + this.emit('idle') + } else if (this.debug) { + return this.emit('debug', () => console.info(this.debugTime())) + } else { + return + } + }, 1000) + } + + start = () => { + this.stop() + if (!this.timer) { + this.reset() + this.startTimer() + } + } + + reset = () => { + const currentTime = new Date().getTime() + this.endTime = currentTime + this.startTime * 1000 + } + + stop = () => { + if (this.timer) { + clearInterval(this.timer) + this.timer = null + } + } + + debugTime = () => { + const currentTime = new Date().getTime() + return `Tiempo restante: ${((this.endTime - currentTime) / 1000).toFixed(0)} segundos` + } +} + +module.exports = IdleState diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index 7321c8978..cef6fe74f 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -9,6 +9,7 @@ const { LIST_REGEX } = require('../io/events') const SingleState = require('../context/state.class') const GlobalState = require('../context/globalState.class') const { generateTime } = require('../utils/hash') +const IdleState = require('../context/idleState.class') const logger = new Console({ stdout: createWriteStream(`${process.cwd()}/core.class.log`), @@ -19,6 +20,7 @@ const loggerQueue = new Console({ const StateHandler = new SingleState() const GlobalStateHandler = new GlobalState() +const idle = new IdleState() /** * [ ] Escuchar eventos del provider asegurarte que los provider emitan eventos @@ -325,6 +327,7 @@ class CoreClass { state, globalState, extensions, + idleState: idle, fallBack: fallBack(flags), flowDynamic: flowDynamic(flags), endFlow: endFlow(flags), From 894eddefe161e7c87f049faa40e91ec1bc649a3f Mon Sep 17 00:00:00 2001 From: "Binho.dev" Date: Wed, 13 Sep 2023 16:01:00 -0300 Subject: [PATCH 5/5] fix(bot): :fire: fix Changed a little code and removed unnecessary codes No breaking changes --- packages/bot/context/idleState.class.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/bot/context/idleState.class.js b/packages/bot/context/idleState.class.js index aa51c9fc4..5678e2560 100755 --- a/packages/bot/context/idleState.class.js +++ b/packages/bot/context/idleState.class.js @@ -17,16 +17,13 @@ class IdleState extends EventEmitter { if (currentTime > this.endTime) { this.stop() this.emit('idle') - } else if (this.debug) { - return this.emit('debug', () => console.info(this.debugTime())) } else { - return + this.debugTime() } }, 1000) } start = () => { - this.stop() if (!this.timer) { this.reset() this.startTimer()