chore: pre-chore

This commit is contained in:
Leifer Mendez
2023-02-04 17:59:45 +01:00
11 changed files with 239 additions and 155 deletions

View File

@@ -1,3 +1,3 @@
{ {
"recommendations": ["xyc.vscode-mdx-preview"] "recommendations": ["xyc.vscode-mdx-preview", "vivaxy.vscode-conventional-commits", "mhutchie.git-graph"]
} }

View File

@@ -2,12 +2,7 @@ const { test } = require('uvu')
const assert = require('uvu/assert') const assert = require('uvu/assert')
const MOCK_DB = require('../packages/database/src/mock') const MOCK_DB = require('../packages/database/src/mock')
const PROVIDER_DB = require('../packages/provider/src/mock') const PROVIDER_DB = require('../packages/provider/src/mock')
const { const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
addKeyword,
createBot,
createFlow,
createProvider,
} = require('../packages/bot/index')
/** /**
* Falsear peticion async * Falsear peticion async
@@ -21,11 +16,7 @@ const fakeHTTP = async (fakeData = []) => {
} }
test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => {
const MOCK_VALUES = [ const MOCK_VALUES = ['¿CUal es tu email?', 'Continuamos....', '¿Cual es tu edad?']
'¿CUal es tu email?',
'Continuamos....',
'¿Cual es tu edad?',
]
const provider = createProvider(PROVIDER_DB) const provider = createProvider(PROVIDER_DB)
const database = new MOCK_DB() const database = new MOCK_DB()
@@ -39,26 +30,20 @@ test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => {
const validation = ctx.body.includes('@') const validation = ctx.body.includes('@')
if (validation) { if (validation) {
const getDataFromApi = await fakeHTTP([ const getDataFromApi = await fakeHTTP(['Gracias por tu email se ha validado de manera correcta'])
'Gracias por tu email se ha validado de manera correcta',
])
return flowDynamic(getDataFromApi) return flowDynamic(getDataFromApi)
} }
return fallBack(validation) return fallBack(validation)
} }
) )
.addAnswer(MOCK_VALUES[1]) .addAnswer(MOCK_VALUES[1])
.addAnswer( .addAnswer(MOCK_VALUES[2], { capture: true }, async (ctx, { flowDynamic, fallBack }) => {
MOCK_VALUES[2],
{ capture: true },
async (ctx, { flowDynamic, fallBack }) => {
if (ctx.body !== '18') { if (ctx.body !== '18') {
await delay(50) await delay(50)
return fallBack(false, 'Ups creo que no eres mayor de edad') return fallBack(false, 'Ups creo que no eres mayor de edad')
} }
return flowDynamic('Bien tu edad es correcta!') return flowDynamic('Bien tu edad es correcta!')
} })
)
.addAnswer('Puedes pasar') .addAnswer('Puedes pasar')
createBot({ createBot({
@@ -98,10 +83,7 @@ test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => {
assert.is('this is not email value', getHistory[1]) assert.is('this is not email value', getHistory[1])
assert.is(MOCK_VALUES[0], getHistory[2]) assert.is(MOCK_VALUES[0], getHistory[2])
assert.is('test@test.com', getHistory[3]) assert.is('test@test.com', getHistory[3])
assert.is( assert.is('1 Gracias por tu email se ha validado de manera correcta', getHistory[4])
'1 Gracias por tu email se ha validado de manera correcta',
getHistory[4]
)
assert.is(MOCK_VALUES[1], getHistory[5]) assert.is(MOCK_VALUES[1], getHistory[5])
assert.is(MOCK_VALUES[2], getHistory[6]) assert.is(MOCK_VALUES[2], getHistory[6])
assert.is('20', getHistory[7]) assert.is('20', getHistory[7])

92
__test__/07-case.test.js Normal file
View File

@@ -0,0 +1,92 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
const MOCK_DB = require('../packages/database/src/mock')
const PROVIDER_DB = require('../packages/provider/src/mock')
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
/**
* Falsear peticion async
* @param {*} fakeData
* @returns
*/
const fakeHTTP = async (fakeData = []) => {
await delay(5)
const data = fakeData.map((u, i) => ({ body: `${i + 1} ${u}` }))
return Promise.resolve(data)
}
let STATE_APP = {}
test(`[Caso - 07] Retornar estado`, async () => {
const MOCK_VALUES = ['¿Cual es tu nombre?', '¿Cual es tu edad?', 'Tu datos son:']
const provider = createProvider(PROVIDER_DB)
const database = new MOCK_DB()
const flujoPrincipal = addKeyword(['hola'])
.addAnswer(
MOCK_VALUES[0],
{
capture: true,
},
async (ctx, { flowDynamic, fallBack }) => {
STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], name: ctx.body }
flowDynamic('Gracias por tu nombre!')
}
)
.addAnswer(
MOCK_VALUES[1],
{
capture: true,
},
async (ctx, { flowDynamic, endFlow }) => {
STATE_APP[ctx.from] = { ...STATE_APP[ctx.from], age: ctx.body }
await flowDynamic('Gracias por tu edad!')
}
)
.addAnswer(MOCK_VALUES[2], null, async (ctx, { flowDynamic }) => {
flowDynamic(`Nombre: ${STATE_APP[ctx.from].name} Edad: ${STATE_APP[ctx.from].age}`)
})
.addAnswer('🤖🤖 Gracias por tu participacion')
createBot({
database,
flow: createFlow([flujoPrincipal]),
provider,
})
provider.delaySendMessage(0, 'message', {
from: '000',
body: 'hola',
})
provider.delaySendMessage(20, 'message', {
from: '000',
body: 'Leifer',
})
provider.delaySendMessage(40, 'message', {
from: '000',
body: '90',
})
await delay(1200)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is(MOCK_VALUES[0], getHistory[0])
assert.is('Leifer', getHistory[1])
assert.is('Gracias por tu nombre!', getHistory[2])
assert.is('¿Cual es tu edad?', getHistory[3])
assert.is('90', getHistory[4])
assert.is('Gracias por tu edad!', getHistory[5])
assert.is('Tu datos son:', getHistory[6])
assert.is('Nombre: Leifer Edad: 90', getHistory[7])
assert.is('🤖🤖 Gracias por tu participacion', getHistory[8])
assert.is(undefined, getHistory[9])
})
test.run()
function delay(ms) {
return new Promise((res) => setTimeout(res, ms))
}

43
__test__/08-case.test.js Normal file
View File

@@ -0,0 +1,43 @@
const { test } = require('uvu')
const assert = require('uvu/assert')
const MOCK_DB = require('../packages/database/src/mock')
const PROVIDER_DB = require('../packages/provider/src/mock')
const { addKeyword, createBot, createFlow, createProvider } = require('../packages/bot/index')
test(`[Caso - 08] Regular expression on keyword`, async () => {
const provider = createProvider(PROVIDER_DB)
const database = new MOCK_DB()
const REGEX_CREDIT_NUMBER = `/(^4[0-9]{12}(?:[0-9]{3})?$)|(^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$)|(3[47][0-9]{13})|(^3(?:0[0-5]|[68][0-9])[0-9]{11}$)|(^6(?:011|5[0-9]{2})[0-9]{12}$)|(^(?:2131|1800|35\d{3})\d{11}$)/gm`
const flujoPrincipal = addKeyword(REGEX_CREDIT_NUMBER, { regex: true })
.addAnswer(`Gracias por proporcionar un numero de tarjeta valido`)
.addAnswer('Fin!')
createBot({
database,
flow: createFlow([flujoPrincipal]),
provider,
})
provider.delaySendMessage(0, 'message', {
from: '000',
body: 'hola',
})
provider.delaySendMessage(20, 'message', {
from: '000',
body: '374245455400126',
})
await delay(40)
const getHistory = database.listHistory.map((i) => i.answer)
assert.is('Gracias por proporcionar un numero de tarjeta valido', getHistory[0])
assert.is('Fin!', getHistory[1])
assert.is(undefined, getHistory[2])
})
test.run()
function delay(ms) {
return new Promise((res) => setTimeout(res, ms))
}

View File

@@ -43,8 +43,7 @@ class CoreClass {
}, },
{ {
event: 'require_action', event: 'require_action',
func: ({ instructions, title = '⚡⚡ ACCIÓN REQUERIDA ⚡⚡' }) => func: ({ instructions, title = '⚡⚡ ACCIÓN REQUERIDA ⚡⚡' }) => printer(instructions, title),
printer(instructions, title),
}, },
{ {
event: 'ready', event: 'ready',
@@ -52,8 +51,7 @@ class CoreClass {
}, },
{ {
event: 'auth_failure', event: 'auth_failure',
func: ({ instructions }) => func: ({ instructions }) => printer(instructions, '⚡⚡ ERROR AUTH ⚡⚡'),
printer(instructions, '⚡⚡ ERROR AUTH ⚡⚡'),
}, },
{ {
@@ -78,9 +76,7 @@ class CoreClass {
if (!body.length) return if (!body.length) return
let prevMsg = await this.databaseClass.getPrevByNumber(from) let prevMsg = await this.databaseClass.getPrevByNumber(from)
const refToContinue = this.flowClass.findBySerialize( const refToContinue = this.flowClass.findBySerialize(prevMsg?.refSerialize)
prevMsg?.refSerialize
)
if (prevMsg?.ref) { if (prevMsg?.ref) {
const ctxByNumber = toCtx({ const ctxByNumber = toCtx({
@@ -93,10 +89,7 @@ class CoreClass {
// 📄 Crar CTX de mensaje (uso private) // 📄 Crar CTX de mensaje (uso private)
const createCtxMessage = (payload = {}, index = 0) => { const createCtxMessage = (payload = {}, index = 0) => {
const body = const body = typeof payload === 'string' ? payload : payload?.body ?? payload?.answer
typeof payload === 'string'
? payload
: payload?.body ?? payload?.answer
const media = payload?.media ?? null const media = payload?.media ?? null
const buttons = payload?.buttons ?? [] const buttons = payload?.buttons ?? []
const capture = payload?.capture ?? false const capture = payload?.capture ?? false
@@ -118,30 +111,16 @@ class CoreClass {
// 📄 Finalizar flujo // 📄 Finalizar flujo
const endFlow = async (message = null) => { const endFlow = async (message = null) => {
prevMsg = null
endFlowFlag = true endFlowFlag = true
if (message) if (message) this.sendProviderAndSave(from, createCtxMessage(message))
this.sendProviderAndSave(from, createCtxMessage(message))
clearQueue() clearQueue()
return sendFlow([])
}
// 📄 Continuar con el siguiente flujo
const continueFlow = async () => {
const cotinueMessage =
this.flowClass.find(refToContinue?.ref, true) || []
sendFlow(cotinueMessage, from, { continue: true })
return return
} }
// 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx // 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx
const sendFlow = async ( const sendFlow = async (messageToSend, numberOrId, options = { prev: prevMsg }) => {
messageToSend, if (options.prev?.options?.capture) await cbEveryCtx(options.prev?.ref)
numberOrId,
options = { continue: false }
) => {
if (!options.continue && prevMsg?.options?.capture)
await cbEveryCtx(prevMsg?.ref)
const queue = [] const queue = []
for (const ctxMessage of messageToSend) { for (const ctxMessage of messageToSend) {
@@ -150,9 +129,7 @@ class CoreClass {
if (delayMs) await delay(delayMs) if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() => QueuePrincipal.enqueue(() =>
Promise.all([ Promise.all([
this.sendProviderAndSave(numberOrId, ctxMessage).then( this.sendProviderAndSave(numberOrId, ctxMessage).then(() => resolveCbEveryCtx(ctxMessage)),
() => resolveCbEveryCtx(ctxMessage)
),
]) ])
) )
} }
@@ -160,20 +137,26 @@ class CoreClass {
} }
// 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje // 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje
const fallBack = async (next = false, message = null) => { const fallBack = async (validation = false, message = null) => {
QueuePrincipal.queue = [] QueuePrincipal.queue = []
if (next) return continueFlow()
return this.sendProviderAndSave(from, { if (validation) {
const currentPrev = await this.databaseClass.getPrevByNumber(from)
const nextFlow = await this.flowClass.find(refToContinue?.ref, true)
const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize)
return sendFlow(filterNextFlow, from, { prev: undefined })
}
await this.sendProviderAndSave(from, {
...prevMsg, ...prevMsg,
answer: answer: typeof message === 'string' ? message : message?.body ?? prevMsg.answer,
typeof message === 'string'
? message
: message?.body ?? prevMsg.answer,
options: { options: {
...prevMsg.options, ...prevMsg.options,
buttons: message?.buttons ?? prevMsg.options?.buttons, buttons: prevMsg.options?.buttons,
}, },
}) })
return
} }
// 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes // 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes
@@ -182,21 +165,33 @@ class CoreClass {
const flowDynamic = async (listMsg = []) => { const flowDynamic = async (listMsg = []) => {
if (!Array.isArray(listMsg)) listMsg = [listMsg] if (!Array.isArray(listMsg)) listMsg = [listMsg]
const parseListMsg = listMsg.map((opt, index) => const parseListMsg = listMsg.map((opt, index) => createCtxMessage(opt, index))
createCtxMessage(opt, index) const currentPrev = await this.databaseClass.getPrevByNumber(from)
)
const skipContinueFlow = async () => {
const nextFlow = await this.flowClass.find(refToContinue?.ref, true)
const filterNextFlow = nextFlow.filter((msg) => msg.refSerialize !== currentPrev?.refSerialize)
const isContinueFlow = filterNextFlow.map((i) => i.keyword).includes(currentPrev?.ref)
return {
continue: !isContinueFlow,
contexts: filterNextFlow,
}
}
if (endFlowFlag) return if (endFlowFlag) return
for (const msg of parseListMsg) { for (const msg of parseListMsg) {
await this.sendProviderAndSave(from, msg) await this.sendProviderAndSave(from, msg)
} }
return continueFlow()
const continueFlowData = await skipContinueFlow()
if (continueFlowData.continue) return sendFlow(continueFlowData.contexts, from, { prev: undefined })
return
} }
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback // 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback
const resolveCbEveryCtx = async (ctxMessage) => { const resolveCbEveryCtx = async (ctxMessage) => {
if (!ctxMessage?.options?.capture) if (!ctxMessage?.options?.capture) return await cbEveryCtx(ctxMessage?.ref)
return await cbEveryCtx(ctxMessage?.ref)
} }
// 📄 Se encarga de revisar si el contexto del mensaje tiene callback y ejecutarlo // 📄 Se encarga de revisar si el contexto del mensaje tiene callback y ejecutarlo
@@ -206,7 +201,6 @@ class CoreClass {
fallBack, fallBack,
flowDynamic, flowDynamic,
endFlow, endFlow,
continueFlow,
}) })
} }
@@ -246,10 +240,9 @@ class CoreClass {
*/ */
sendProviderAndSave = (numberOrId, ctxMessage) => { sendProviderAndSave = (numberOrId, ctxMessage) => {
const { answer } = ctxMessage const { answer } = ctxMessage
return Promise.all([ return this.providerClass
this.providerClass.sendMessage(numberOrId, answer, ctxMessage), .sendMessage(numberOrId, answer, ctxMessage)
this.databaseClass.save({ ...ctxMessage, from: numberOrId }), .then(() => this.databaseClass.save({ ...ctxMessage, from: numberOrId }))
])
} }
/** /**
@@ -279,9 +272,7 @@ class CoreClass {
for (const ctxMessage of messageToSend) { for (const ctxMessage of messageToSend) {
const delayMs = ctxMessage?.options?.delay || 0 const delayMs = ctxMessage?.options?.delay || 0
if (delayMs) await delay(delayMs) if (delayMs) await delay(delayMs)
QueuePrincipal.enqueue(() => QueuePrincipal.enqueue(() => this.sendProviderAndSave(numberOrId, ctxMessage))
this.sendProviderAndSave(numberOrId, ctxMessage)
)
} }
return Promise.all(queue) return Promise.all(queue)
} }

View File

@@ -25,9 +25,17 @@ class FlowClass {
let refSymbol = null let refSymbol = null
overFlow = overFlow ?? this.flowSerialize overFlow = overFlow ?? this.flowSerialize
const customRegex = (str = null) => {
if (typeof str !== 'string') return
const instanceRegex = new RegExp(str)
return instanceRegex.test(str)
}
/** Retornar expresion regular para buscar coincidencia */ /** Retornar expresion regular para buscar coincidencia */
const mapSensitive = (str, flag = false) => { const mapSensitive = (str, mapOptions = { sensitive: false, regex: false }) => {
const regexSensitive = flag ? 'g' : 'i' if (mapOptions.regex) return customRegex(str)
const regexSensitive = mapOptions.sensitive ? 'g' : 'i'
if (Array.isArray(str)) { if (Array.isArray(str)) {
return new RegExp(str.join('|'), regexSensitive) return new RegExp(str.join('|'), regexSensitive)
} }
@@ -36,6 +44,7 @@ class FlowClass {
const findIn = (keyOrWord, symbol = false, flow = overFlow) => { const findIn = (keyOrWord, symbol = false, flow = overFlow) => {
const sensitive = refSymbol?.options?.sensitive || false const sensitive = refSymbol?.options?.sensitive || false
const regex = refSymbol?.options?.regex || false
capture = refSymbol?.options?.capture || false capture = refSymbol?.options?.capture || false
if (capture) return messages if (capture) return messages
@@ -46,7 +55,7 @@ class FlowClass {
if (refSymbol?.ref) findIn(refSymbol.ref, true) if (refSymbol?.ref) findIn(refSymbol.ref, true)
} else { } else {
refSymbol = flow.find((c) => { refSymbol = flow.find((c) => {
return mapSensitive(c.keyword, sensitive).test(keyOrWord) return mapSensitive(c.keyword, { sensitive, regex }).test(keyOrWord)
}) })
if (refSymbol?.ref) findIn(refSymbol.ref, true) if (refSymbol?.ref) findIn(refSymbol.ref, true)
return messages return messages
@@ -56,8 +65,7 @@ class FlowClass {
return messages return messages
} }
findBySerialize = (refSerialize) => findBySerialize = (refSerialize) => this.flowSerialize.find((r) => r.refSerialize === refSerialize)
this.flowSerialize.find((r) => r.refSerialize === refSerialize)
findIndexByRef = (ref) => this.flowSerialize.findIndex((r) => r.ref === ref) findIndexByRef = (ref) => this.flowSerialize.findIndex((r) => r.ref === ref)
} }

View File

@@ -8,12 +8,14 @@ const { toJson } = require('./toJson')
* @param {*} options {sensitive:boolean} default false * @param {*} options {sensitive:boolean} default false
*/ */
const addKeyword = (keyword, options) => { const addKeyword = (keyword, options) => {
if (typeof keyword !== 'string' && !Array.isArray(keyword)) {
throw new Error('DEBE_SER_STRING_ARRAY_REGEX')
}
const parseOptions = () => { const parseOptions = () => {
const defaultProperties = { const defaultProperties = {
sensitive: sensitive: typeof options?.sensitive === 'boolean' ? options?.sensitive : false,
typeof options?.sensitive === 'boolean' regex: typeof options?.regex === 'boolean' ? options?.regex : false,
? options?.sensitive
: false,
} }
return defaultProperties return defaultProperties

View File

@@ -1,6 +1,6 @@
{ {
"name": "@bot-whatsapp/bot", "name": "@bot-whatsapp/bot",
"version": "0.0.91-alpha.0", "version": "0.0.96-alpha.0",
"description": "", "description": "",
"main": "./lib/bundle.bot.cjs", "main": "./lib/bundle.bot.cjs",
"scripts": { "scripts": {

View File

@@ -10,7 +10,10 @@ class MockDatabase {
constructor() {} constructor() {}
getPrevByNumber = (from) => { getPrevByNumber = (from) => {
const history = this.listHistory.slice().reverse() const history = this.listHistory
.slice()
.reverse()
.filter((i) => !!i.keyword)
return history.find((a) => a.from === from) return history.find((a) => a.from === from)
} }

View File

@@ -7,18 +7,9 @@ const { join } = require('path')
const { createWriteStream, readFileSync } = require('fs') const { createWriteStream, readFileSync } = require('fs')
const { Console } = require('console') const { Console } = require('console')
const { const { default: makeWASocket, useMultiFileAuthState, Browsers, DisconnectReason } = require('@adiwajshing/baileys')
default: makeWASocket,
useMultiFileAuthState,
Browsers,
DisconnectReason,
} = require('@adiwajshing/baileys')
const { const { baileyGenerateImage, baileyCleanNumber, baileyIsValidNumber } = require('./utils')
baileyGenerateImage,
baileyCleanNumber,
baileyIsValidNumber,
} = require('./utils')
const { generalDownload } = require('../../common/download') const { generalDownload } = require('../../common/download')
@@ -46,9 +37,7 @@ class BaileysProvider extends ProviderClass {
*/ */
initBailey = async () => { initBailey = async () => {
const NAME_DIR_SESSION = `${this.globalVendorArgs.name}_sessions` const NAME_DIR_SESSION = `${this.globalVendorArgs.name}_sessions`
const { state, saveCreds } = await useMultiFileAuthState( const { state, saveCreds } = await useMultiFileAuthState(NAME_DIR_SESSION)
NAME_DIR_SESSION
)
this.saveCredsGlobal = saveCreds this.saveCredsGlobal = saveCreds
try { try {
@@ -57,7 +46,7 @@ class BaileysProvider extends ProviderClass {
auth: state, auth: state,
browser: Browsers.macOS('Desktop'), browser: Browsers.macOS('Desktop'),
syncFullHistory: false, syncFullHistory: false,
logger: pino({ level: 'error' }), logger: pino({ level: 'fatal' }),
}) })
sock.ev.on('connection.update', async (update) => { sock.ev.on('connection.update', async (update) => {
@@ -96,10 +85,7 @@ class BaileysProvider extends ProviderClass {
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
], ],
}) })
await baileyGenerateImage( await baileyGenerateImage(qr, `${this.globalVendorArgs.name}.qr.png`)
qr,
`${this.globalVendorArgs.name}.qr.png`
)
} }
}) })
@@ -131,9 +117,10 @@ class BaileysProvider extends ProviderClass {
const [messageCtx] = messages const [messageCtx] = messages
let payload = { let payload = {
...messageCtx, ...messageCtx,
body: messageCtx?.message?.conversation, body: messageCtx?.message?.extendedTextMessage?.text ?? messageCtx?.message?.conversation,
from: messageCtx?.key?.remoteJid, from: messageCtx?.key?.remoteJid,
} }
if (payload.from === 'status@broadcast') return if (payload.from === 'status@broadcast') return
if (payload?.key?.fromMe) return if (payload?.key?.fromMe) return
@@ -142,9 +129,7 @@ class BaileysProvider extends ProviderClass {
return return
} }
const btnCtx = const btnCtx = payload?.message?.buttonsResponseMessage?.selectedDisplayText
payload?.message?.buttonsResponseMessage
?.selectedDisplayText
if (btnCtx) payload.body = btnCtx if (btnCtx) payload.body = btnCtx
@@ -174,12 +159,9 @@ class BaileysProvider extends ProviderClass {
const fileDownloaded = await generalDownload(imageUrl) const fileDownloaded = await generalDownload(imageUrl)
const mimeType = mime.lookup(fileDownloaded) const mimeType = mime.lookup(fileDownloaded)
if (mimeType.includes('image')) if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text)
return this.sendImage(number, fileDownloaded, text) if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded, text)
if (mimeType.includes('video')) if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded, text)
return this.sendVideo(number, fileDownloaded, text)
if (mimeType.includes('audio'))
return this.sendAudio(number, fileDownloaded, text)
return this.sendFile(number, fileDownloaded) return this.sendFile(number, fileDownloaded)
} }
@@ -294,10 +276,8 @@ class BaileysProvider extends ProviderClass {
sendMessage = async (numberIn, message, { options }) => { sendMessage = async (numberIn, message, { options }) => {
const number = baileyCleanNumber(numberIn) const number = baileyCleanNumber(numberIn)
if (options?.buttons?.length) if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons)
return this.sendButtons(number, message, options.buttons) if (options?.media) return this.sendMedia(number, options.media, message)
if (options?.media)
return this.sendMedia(number, options.media, message)
return this.sendText(number, message) return this.sendText(number, message)
} }
@@ -332,12 +312,7 @@ class BaileysProvider extends ProviderClass {
* @example await sendContact("xxxxxxxxxxx@c.us" || "xxxxxxxxxxxxxxxxxx@g.us", "+xxxxxxxxxxx", "Robin Smith", messages) * @example await sendContact("xxxxxxxxxxx@c.us" || "xxxxxxxxxxxxxxxxxx@g.us", "+xxxxxxxxxxx", "Robin Smith", messages)
*/ */
sendContact = async ( sendContact = async (remoteJid, contactNumber, displayName, messages = null) => {
remoteJid,
contactNumber,
displayName,
messages = null
) => {
const cleanContactNumber = contactNumber.replaceAll(' ', '') const cleanContactNumber = contactNumber.replaceAll(' ', '')
const waid = cleanContactNumber.replace('+', '') const waid = cleanContactNumber.replace('+', '')

View File

@@ -2,11 +2,7 @@ const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js')
const { ProviderClass } = require('@bot-whatsapp/bot') const { ProviderClass } = require('@bot-whatsapp/bot')
const { Console } = require('console') const { Console } = require('console')
const { createWriteStream, readFileSync } = require('fs') const { createWriteStream, readFileSync } = require('fs')
const { const { wwebCleanNumber, wwebGenerateImage, wwebIsValidNumber } = require('./utils')
wwebCleanNumber,
wwebGenerateImage,
wwebIsValidNumber,
} = require('./utils')
const logger = new Console({ const logger = new Console({
stdout: createWriteStream('./log'), stdout: createWriteStream('./log'),
@@ -32,11 +28,7 @@ class WebWhatsappProvider extends ProviderClass {
}), }),
puppeteer: { puppeteer: {
headless: true, headless: true,
args: [ args: ['--no-sandbox', '--disable-setuid-sandbox', '--unhandled-rejections=strict'],
'--no-sandbox',
'--disable-setuid-sandbox',
'--unhandled-rejections=strict',
],
//executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', //executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
}, },
}) })
@@ -80,10 +72,7 @@ class WebWhatsappProvider extends ProviderClass {
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
], ],
}) })
await wwebGenerateImage( await wwebGenerateImage(qr, `${this.globalVendorArgs.name}.qr.png`)
qr,
`${this.globalVendorArgs.name}.qr.png`
)
}, },
}, },
{ {
@@ -116,6 +105,9 @@ class WebWhatsappProvider extends ProviderClass {
* @returns * @returns
*/ */
sendButtons = async (number, message, buttons = []) => { sendButtons = async (number, message, buttons = []) => {
console.log(`🚩 ¿No te funciona los botones? Intenta instalar`)
console.log(`npm i github:pedroslopez/whatsapp-web.js#fix-buttons-list`)
const buttonMessage = new Buttons(message, buttons, '', '') const buttonMessage = new Buttons(message, buttons, '', '')
return this.vendor.sendMessage(number, buttonMessage) return this.vendor.sendMessage(number, buttonMessage)
} }
@@ -226,12 +218,9 @@ class WebWhatsappProvider extends ProviderClass {
const fileDownloaded = await generalDownload(mediaUrl) const fileDownloaded = await generalDownload(mediaUrl)
const mimeType = mime.lookup(fileDownloaded) const mimeType = mime.lookup(fileDownloaded)
if (mimeType.includes('image')) if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text)
return this.sendImage(number, fileDownloaded, text) if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded)
if (mimeType.includes('video')) if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded)
return this.sendVideo(number, fileDownloaded)
if (mimeType.includes('audio'))
return this.sendAudio(number, fileDownloaded, text)
return this.sendFile(number, fileDownloaded) return this.sendFile(number, fileDownloaded)
} }
@@ -245,8 +234,7 @@ class WebWhatsappProvider extends ProviderClass {
*/ */
sendMessage = async (userId, message, { options }) => { sendMessage = async (userId, message, { options }) => {
const number = wwebCleanNumber(userId) const number = wwebCleanNumber(userId)
if (options?.buttons?.length) if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons)
return this.sendButtons(number, message, options.buttons)
if (options?.media) return this.sendMedia(number, options.media) if (options?.media) return this.sendMedia(number, options.media)
return this.sendText(number, message) return this.sendText(number, message)
} }