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

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

View File

@@ -25,9 +25,17 @@ class FlowClass {
let refSymbol = null
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 */
const mapSensitive = (str, flag = false) => {
const regexSensitive = flag ? 'g' : 'i'
const mapSensitive = (str, mapOptions = { sensitive: false, regex: false }) => {
if (mapOptions.regex) return customRegex(str)
const regexSensitive = mapOptions.sensitive ? 'g' : 'i'
if (Array.isArray(str)) {
return new RegExp(str.join('|'), regexSensitive)
}
@@ -36,6 +44,7 @@ class FlowClass {
const findIn = (keyOrWord, symbol = false, flow = overFlow) => {
const sensitive = refSymbol?.options?.sensitive || false
const regex = refSymbol?.options?.regex || false
capture = refSymbol?.options?.capture || false
if (capture) return messages
@@ -46,7 +55,7 @@ class FlowClass {
if (refSymbol?.ref) findIn(refSymbol.ref, true)
} else {
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)
return messages
@@ -56,8 +65,7 @@ class FlowClass {
return messages
}
findBySerialize = (refSerialize) =>
this.flowSerialize.find((r) => r.refSerialize === refSerialize)
findBySerialize = (refSerialize) => this.flowSerialize.find((r) => r.refSerialize === refSerialize)
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
*/
const addKeyword = (keyword, options) => {
if (typeof keyword !== 'string' && !Array.isArray(keyword)) {
throw new Error('DEBE_SER_STRING_ARRAY_REGEX')
}
const parseOptions = () => {
const defaultProperties = {
sensitive:
typeof options?.sensitive === 'boolean'
? options?.sensitive
: false,
sensitive: typeof options?.sensitive === 'boolean' ? options?.sensitive : false,
regex: typeof options?.regex === 'boolean' ? options?.regex : false,
}
return defaultProperties

View File

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

View File

@@ -10,7 +10,10 @@ class MockDatabase {
constructor() {}
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)
}

View File

@@ -7,18 +7,9 @@ const { join } = require('path')
const { createWriteStream, readFileSync } = require('fs')
const { Console } = require('console')
const {
default: makeWASocket,
useMultiFileAuthState,
Browsers,
DisconnectReason,
} = require('@adiwajshing/baileys')
const { default: makeWASocket, useMultiFileAuthState, Browsers, DisconnectReason } = require('@adiwajshing/baileys')
const {
baileyGenerateImage,
baileyCleanNumber,
baileyIsValidNumber,
} = require('./utils')
const { baileyGenerateImage, baileyCleanNumber, baileyIsValidNumber } = require('./utils')
const { generalDownload } = require('../../common/download')
@@ -46,9 +37,7 @@ class BaileysProvider extends ProviderClass {
*/
initBailey = async () => {
const NAME_DIR_SESSION = `${this.globalVendorArgs.name}_sessions`
const { state, saveCreds } = await useMultiFileAuthState(
NAME_DIR_SESSION
)
const { state, saveCreds } = await useMultiFileAuthState(NAME_DIR_SESSION)
this.saveCredsGlobal = saveCreds
try {
@@ -57,7 +46,7 @@ class BaileysProvider extends ProviderClass {
auth: state,
browser: Browsers.macOS('Desktop'),
syncFullHistory: false,
logger: pino({ level: 'error' }),
logger: pino({ level: 'fatal' }),
})
sock.ev.on('connection.update', async (update) => {
@@ -96,10 +85,7 @@ class BaileysProvider extends ProviderClass {
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
],
})
await baileyGenerateImage(
qr,
`${this.globalVendorArgs.name}.qr.png`
)
await baileyGenerateImage(qr, `${this.globalVendorArgs.name}.qr.png`)
}
})
@@ -131,9 +117,10 @@ class BaileysProvider extends ProviderClass {
const [messageCtx] = messages
let payload = {
...messageCtx,
body: messageCtx?.message?.conversation,
body: messageCtx?.message?.extendedTextMessage?.text ?? messageCtx?.message?.conversation,
from: messageCtx?.key?.remoteJid,
}
if (payload.from === 'status@broadcast') return
if (payload?.key?.fromMe) return
@@ -142,9 +129,7 @@ class BaileysProvider extends ProviderClass {
return
}
const btnCtx =
payload?.message?.buttonsResponseMessage
?.selectedDisplayText
const btnCtx = payload?.message?.buttonsResponseMessage?.selectedDisplayText
if (btnCtx) payload.body = btnCtx
@@ -174,12 +159,9 @@ class BaileysProvider extends ProviderClass {
const fileDownloaded = await generalDownload(imageUrl)
const mimeType = mime.lookup(fileDownloaded)
if (mimeType.includes('image'))
return this.sendImage(number, fileDownloaded, text)
if (mimeType.includes('video'))
return this.sendVideo(number, fileDownloaded, text)
if (mimeType.includes('audio'))
return this.sendAudio(number, fileDownloaded, text)
if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text)
if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded, text)
if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded, text)
return this.sendFile(number, fileDownloaded)
}
@@ -294,10 +276,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?.media)
return this.sendMedia(number, options.media, message)
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)
}
@@ -332,12 +312,7 @@ class BaileysProvider extends ProviderClass {
* @example await sendContact("xxxxxxxxxxx@c.us" || "xxxxxxxxxxxxxxxxxx@g.us", "+xxxxxxxxxxx", "Robin Smith", messages)
*/
sendContact = async (
remoteJid,
contactNumber,
displayName,
messages = null
) => {
sendContact = async (remoteJid, contactNumber, displayName, messages = null) => {
const cleanContactNumber = contactNumber.replaceAll(' ', '')
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 { Console } = require('console')
const { createWriteStream, readFileSync } = require('fs')
const {
wwebCleanNumber,
wwebGenerateImage,
wwebIsValidNumber,
} = require('./utils')
const { wwebCleanNumber, wwebGenerateImage, wwebIsValidNumber } = require('./utils')
const logger = new Console({
stdout: createWriteStream('./log'),
@@ -32,11 +28,7 @@ class WebWhatsappProvider extends ProviderClass {
}),
puppeteer: {
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--unhandled-rejections=strict',
],
args: ['--no-sandbox', '--disable-setuid-sandbox', '--unhandled-rejections=strict'],
//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`,
],
})
await wwebGenerateImage(
qr,
`${this.globalVendorArgs.name}.qr.png`
)
await wwebGenerateImage(qr, `${this.globalVendorArgs.name}.qr.png`)
},
},
{
@@ -116,6 +105,9 @@ class WebWhatsappProvider extends ProviderClass {
* @returns
*/
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, '', '')
return this.vendor.sendMessage(number, buttonMessage)
}
@@ -226,12 +218,9 @@ class WebWhatsappProvider extends ProviderClass {
const fileDownloaded = await generalDownload(mediaUrl)
const mimeType = mime.lookup(fileDownloaded)
if (mimeType.includes('image'))
return this.sendImage(number, fileDownloaded, text)
if (mimeType.includes('video'))
return this.sendVideo(number, fileDownloaded)
if (mimeType.includes('audio'))
return this.sendAudio(number, fileDownloaded, text)
if (mimeType.includes('image')) return this.sendImage(number, fileDownloaded, text)
if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded)
if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded)
return this.sendFile(number, fileDownloaded)
}
@@ -245,8 +234,7 @@ class WebWhatsappProvider extends ProviderClass {
*/
sendMessage = async (userId, message, { options }) => {
const number = wwebCleanNumber(userId)
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)
return this.sendText(number, message)
}