diff --git a/packages/bot/io/flow.class.js b/packages/bot/io/flow.class.js index 2c18268e7..cfd4afd1a 100644 --- a/packages/bot/io/flow.class.js +++ b/packages/bot/io/flow.class.js @@ -8,10 +8,7 @@ class FlowClass { if (!Array.isArray(_flow)) throw new Error('Esto debe ser un ARRAY') this.flowRaw = _flow - this.allCallbacks = _flow - .map((cbIn) => cbIn.ctx.callbacks) - .flat(2) - .map((c, i) => ({ callback: c?.callback, index: i })) + this.getAllCb(this.flowRaw) const mergeToJsonSerialize = Object.keys(_flow) .map((indexObjectFlow) => _flow[indexObjectFlow].toJson()) @@ -20,6 +17,17 @@ class FlowClass { this.flowSerialize = toSerialize(mergeToJsonSerialize) } + /** + * Buscar y aplanar todos los callbacks + * @param {*} inFlow + */ + getAllCb = (inFlow) => { + this.allCallbacks = inFlow + .map((cbIn) => cbIn.ctx.callbacks) + .flat(2) + .map((c, i) => ({ callback: c?.callback, index: i })) + } + find = (keyOrWord, symbol = false, overFlow = null) => { keyOrWord = `${keyOrWord}` let capture = false diff --git a/packages/cli/interactive/index.js b/packages/cli/interactive/index.js index 3dc16c494..89ee601aa 100644 --- a/packages/cli/interactive/index.js +++ b/packages/cli/interactive/index.js @@ -1,8 +1,8 @@ const prompts = require('prompts') -const { yellow, red, cyan, bgMagenta } = require('kleur') -const { copyBaseApp } = require('../create-app') const { join } = require('path') +const { yellow, red, cyan, bgMagenta } = require('kleur') const { existsSync } = require('fs') +const { copyBaseApp } = require('../create-app') const { checkNodeVersion, checkOs } = require('../check') const bannerDone = () => { @@ -48,9 +48,9 @@ const startInteractive = async () => { message: '¿Cuál base de datos quieres utilizar?', choices: [ { title: 'Memory', value: 'memory' }, + { title: 'Json', value: 'json' }, { title: 'Mongo', value: 'mongo' }, { title: 'MySQL', value: 'mysql' }, - { title: 'Json', value: 'json', disabled: true }, ], max: 1, hint: 'Espacio para seleccionar', diff --git a/packages/provider/src/baileys/index.js b/packages/provider/src/baileys/index.js index 7ae47594d..0ecd18c37 100644 --- a/packages/provider/src/baileys/index.js +++ b/packages/provider/src/baileys/index.js @@ -14,6 +14,7 @@ const { baileyGenerateImage, baileyCleanNumber, baileyIsValidNumber, + baileyDownloadMedia, } = require('./utils') const logger = new Console({ @@ -39,12 +40,43 @@ class BaileysProvider extends ProviderClass { initBailey = async () => { const { state, saveCreds } = await useMultiFileAuthState('sessions') this.saveCredsGlobal = saveCreds + try { - this.vendor = makeWASocket({ + const sock = makeWASocket({ printQRInTerminal: false, auth: state, logger: pino({ level: 'error' }), }) + + sock.ev.on('connection.update', async (update) => { + const { connection, lastDisconnect, qr } = update + + if (connection === 'close') { + const shouldReconnect = + lastDisconnect?.error?.output?.statusCode !== + DisconnectReason.loggedOut + + if (shouldReconnect) { + await saveCreds() + this.initBailey() + } + } + + if (qr) { + this.emit('require_action', { + instructions: [ + `Debes escanear el QR Code para iniciar session reivsa qr.png`, + `Recuerda que el QR se actualiza cada minuto `, + `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, + ], + }) + await baileyGenerateImage(qr) + } + + if (connection === 'open') this.emit('ready', true) + }) + + this.vendor = sock } catch (e) { logger.log(e) this.emit('auth_failure', [ @@ -64,25 +96,9 @@ class BaileysProvider extends ProviderClass { */ busEvents = () => [ { - event: 'connection.update', - func: async ({ qr, connection, lastDisconnect }) => { - const statusCode = lastDisconnect?.error?.output?.statusCode - - if (statusCode && statusCode !== DisconnectReason.loggedOut) - this.initBailey() - - if (qr) { - this.emit('require_action', { - instructions: [ - `Debes escanear el QR Code para iniciar session reivsa qr.png`, - `Recuerda que el QR se actualiza cada minuto `, - `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, - ], - }) - await baileyGenerateImage(qr) - } - - if (connection === 'open') this.emit('ready', true) + event: 'creds.update', + func: async () => { + await this.saveCredsGlobal() }, }, { @@ -95,13 +111,20 @@ class BaileysProvider extends ProviderClass { body: messageCtx?.message?.conversation, from: messageCtx?.key?.remoteJid, } - if (payload.from === 'status@broadcast') { - return - } + if (payload.from === 'status@broadcast') return + + if (payload?.key?.fromMe) return if (!baileyIsValidNumber(payload.from)) { return } + + const btnCtx = + payload?.message?.templateButtonReplyMessage + ?.selectedDisplayText + + if (btnCtx) payload.body = btnCtx + payload.from = baileyCleanNumber(payload.from, true) this.emit('message', payload) }, @@ -124,8 +147,9 @@ class BaileysProvider extends ProviderClass { */ sendMedia = async (number, imageUrl, text) => { - await this.vendor.sendMessage(number, { - image: { url: imageUrl }, + const fileDownloaded = await baileyDownloadMedia(imageUrl) + return this.vendor.sendMessage(number, { + image: { url: fileDownloaded }, text, }) } @@ -186,17 +210,21 @@ class BaileysProvider extends ProviderClass { * @example await sendMessage("+XXXXXXXXXXX", "Your Text", "Your Footer", [{"buttonId": "id", "buttonText": {"displayText": "Button"}, "type": 1}]) */ - sendButtons = async (number, text, footer, buttons) => { + sendButtons = async (number, text, buttons) => { const numberClean = number.replace('+', '') + const templateButtons = buttons.map((btn, i) => ({ + index: `${i}`, + quickReplyButton: { + displayText: btn.body, + id: `id-btn-${i}`, + }, + })) - const buttonMessage = { - text: text, - footer: footer, - buttons: buttons, - headerType: 1, - } - - await this.vendor.sendMessage(`${numberClean}@c.us`, buttonMessage) + return this.vendor.sendMessage(`${numberClean}@c.us`, { + text, + footer: '', + templateButtons: templateButtons, + }) } /** @@ -209,8 +237,8 @@ class BaileysProvider extends ProviderClass { sendMessage = async (numberIn, message, { options }) => { const number = baileyCleanNumber(numberIn) - // if (options?.buttons?.length) - // return this.sendButtons(number, message, options.buttons) + if (options?.buttons?.length) + return this.sendButtons(number, message, options.buttons) if (options?.media) return this.sendMedia(number, options.media, message) return this.sendText(number, message) diff --git a/packages/provider/src/baileys/utils.js b/packages/provider/src/baileys/utils.js index 40efa61b1..ab5b18d63 100644 --- a/packages/provider/src/baileys/utils.js +++ b/packages/provider/src/baileys/utils.js @@ -1,6 +1,9 @@ const { createWriteStream } = require('fs') const combineImage = require('combine-image') const qr = require('qr-image') +const { tmpdir } = require('os') +const http = require('http') +const https = require('https') const baileyCleanNumber = (number, full = false) => { number = number.replace('@s.whatsapp.net', '') @@ -38,4 +41,38 @@ const baileyIsValidNumber = (rawNumber) => { return !exist } -module.exports = { baileyCleanNumber, baileyGenerateImage, baileyIsValidNumber } +/** + * Incompleta + * Descargar archivo multimedia para enviar + * @param {*} url + * @returns + */ +const baileyDownloadMedia = (url) => { + return new Promise((resolve, reject) => { + const ext = url.split('.').pop() + const checkProtocol = url.includes('https:') + const handleHttp = checkProtocol ? https : http + const name = `tmp-${Date.now()}.${ext}` + const fullPath = `${tmpdir()}/${name}` + const file = createWriteStream(fullPath) + handleHttp.get(url, function (response) { + response.pipe(file) + file.on('finish', function () { + file.close() + resolve(fullPath) + }) + file.on('error', function () { + console.log('errro') + file.close() + reject(null) + }) + }) + }) +} + +module.exports = { + baileyCleanNumber, + baileyGenerateImage, + baileyIsValidNumber, + baileyDownloadMedia, +} diff --git a/packages/provider/src/venom/index.js b/packages/provider/src/venom/index.js index 645e80955..375e2d4e2 100644 --- a/packages/provider/src/venom/index.js +++ b/packages/provider/src/venom/index.js @@ -105,6 +105,29 @@ class VenomProvider extends ProviderClass { } } + /** + * Enviar botones + * @private + * @param {*} number + * @param {*} message + * @param {*} buttons [] + * @returns + */ + sendButtons = async (number, message, buttons = []) => { + const NOTE_VENOM_BUTTON = [ + `Actualmente VENOM tiene problemas con la API`, + `para el envio de Botones`, + ].join('\n') + + console.log(`[NOTA]: ${NOTE_VENOM_BUTTON}`) + + const buttonToStr = [message] + .concat(buttons.map((btn) => `${btn.body}`)) + .join(`\n`) + return this.vendor.sendText(number, buttonToStr) + // return this.vendor.sendButtons(number, "Title", buttons1, "Description"); + } + /** * Enviar imagen o multimedia * @param {*} number diff --git a/starters/apps/base-wweb-memory/package.json b/starters/apps/base-wweb-memory/package.json index 6713a3059..0168dffd0 100644 --- a/starters/apps/base-wweb-memory/package.json +++ b/starters/apps/base-wweb-memory/package.json @@ -9,7 +9,7 @@ }, "keywords": [], "dependencies": { - "whatsapp-web.js": "^1.18.3", + "whatsapp-web.js": "^1.18.4", "@bot-whatsapp/bot": "latest", "@bot-whatsapp/cli": "latest", "@bot-whatsapp/database": "latest", diff --git a/starters/apps/base-wweb-mongo/package.json b/starters/apps/base-wweb-mongo/package.json index 9e323ddac..ea6aae199 100644 --- a/starters/apps/base-wweb-mongo/package.json +++ b/starters/apps/base-wweb-mongo/package.json @@ -9,7 +9,7 @@ }, "keywords": [], "dependencies": { - "whatsapp-web.js": "^1.18.3", + "whatsapp-web.js": "^1.18.4", "@bot-whatsapp/bot": "latest", "@bot-whatsapp/cli": "latest", "@bot-whatsapp/database": "latest", diff --git a/starters/apps/base-wweb-mysql/package.json b/starters/apps/base-wweb-mysql/package.json index 3ab73d5bc..b09f470b1 100644 --- a/starters/apps/base-wweb-mysql/package.json +++ b/starters/apps/base-wweb-mysql/package.json @@ -9,7 +9,7 @@ }, "keywords": [], "dependencies": { - "whatsapp-web.js": "^1.18.3", + "whatsapp-web.js": "^1.18.4", "@bot-whatsapp/bot": "latest", "@bot-whatsapp/cli": "latest", "@bot-whatsapp/database": "latest",