Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Leifer Mendez
2022-12-14 18:50:58 +01:00
8 changed files with 189 additions and 62 deletions

View File

@@ -17,6 +17,7 @@
"./mock": "./lib/mock/index.cjs", "./mock": "./lib/mock/index.cjs",
"./twilio": "./lib/twilio/index.cjs", "./twilio": "./lib/twilio/index.cjs",
"./web-whatsapp": "./lib/web-whatsapp/index.cjs", "./web-whatsapp": "./lib/web-whatsapp/index.cjs",
"./venom": "./lib/venom/index.cjs" "./venom": "./lib/venom/index.cjs",
"./baileys": "./lib/baileys/index.cjs"
} }
} }

View File

@@ -39,4 +39,13 @@ module.exports = [
}, },
plugins: [commonjs()], plugins: [commonjs()],
}, },
{
input: join(__dirname, 'src', 'baileys', 'index.js'),
output: {
banner: banner['banner.output'].join(''),
file: join(__dirname, 'lib', 'baileys', 'index.cjs'),
format: 'cjs',
},
plugins: [commonjs()],
},
] ]

View File

@@ -1,79 +1,171 @@
const { ProviderClass } = require('@bot-whatsapp/bot') const { ProviderClass } = require('@bot-whatsapp/bot')
const PINO = require('pino') const pino = require('pino')
const makeWASocket = require('@adiwajshing/baileys').default const {
const { useMultiFileAuthState } = require('@adiwajshing/baileys') default: makeWASocket,
useMultiFileAuthState,
} = require('@adiwajshing/baileys')
const {
baileyGenerateImage,
baileyCleanNumber,
baileyIsValidNumber,
} = require('./utils')
class Baileys extends ProviderClass { /**
* ⚙️ BaileysProvider: Es una clase tipo adaptor
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
* https://github.com/adiwajshing/Baileys
*/
class BaileysProvider extends ProviderClass {
vendor
constructor() { constructor() {
super() super()
this.sock this.initBailey().then(() => this.initBusEvents())
} }
async baileys() { /**
const { state, saveCreds } = await useMultiFileAuthState( * Iniciar todo Bailey
'baileys_auth_whatsapp' */
) async initBailey() {
const { state, saveCreds } = await useMultiFileAuthState('sessions')
this.sock = await makeWASocket({ try {
printQRInTerminal: true, this.vendor = makeWASocket({
auth: state, printQRInTerminal: false,
logger: PINO({ level: 'error' }), auth: state,
}) logger: pino({ level: 'error' }),
})
this.vendor.ev.on(
'connection.update',
async ({ qr, connection, lastDisconnect }) => {
if (qr) baileyGenerateImage(qr)
if (connection === 'open') this.emit('ready', true)
if (lastDisconnect?.error) {
saveCreds()
this.initBailey()
}
}
)
} catch (e) {
this.emit('error', e)
}
}
/**
* Mapeamos los eventos nativos a los que la clase Provider espera
* para tener un standar de eventos
* @returns
*/
busEvents = () => [
{
event: 'connection.update',
func: async ({ qr, connection, lastDisconnect }) => {
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`,
],
})
baileyGenerateImage(qr)
}
this.sock.ev.on(
'connection.update',
({ connection, lastDisconnect }) => {
if (lastDisconnect?.error) { if (lastDisconnect?.error) {
saveCreds() this.emit('require_action', {
instructions: [
this.baileys() `Algo sucedio reinicia el bot o revisa tu whatsapp`,
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
],
})
} }
if (connection === 'open') { if (connection === 'open') this.emit('ready', true)
console.log('Baileys is connected') },
},
{
event: 'messages.upsert',
func: ({ messages }) => {
const [messageCtx] = messages
let payload = {
...messageCtx,
body: messageCtx?.message?.conversation,
from: messageCtx?.key?.remoteJid,
} }
} if (payload.from === 'status@broadcast') {
) return
}
if (!baileyIsValidNumber(payload.from)) {
return
}
payload.from = baileyCleanNumber(payload.from, true)
this.emit('message', payload)
},
},
]
initBusEvents = () => {
const listEvents = this.busEvents()
for (const { event, func } of listEvents) {
this.vendor.ev.on(event, func)
}
} }
/** /**
* * @alpha
* @param {string} number * @param {string} number
* @param {string} message * @param {string} message
* @example await sendMessage('+51925465621', 'Hello World') * @example await sendMessage('+XXXXXXXXXXX', 'https://dominio.com/imagen.jpg' | 'img/imagen.jpg')
*/
async sendMessage(number, message) {
const numberClean = number.replace('+', '')
await this.sock.sendMessage(`${numberClean}@c.us`, { text: message })
}
/**
*
* @param {string} number
* @param {string} message
* @example await sendMessage('+51925465621', 'https://dominio.com/imagen.jpg' | 'img/imagen.jpg')
*/ */
async sendImage(number, imageUrl) { sendMedia = async (number, imageUrl) => {
const numberClean = number.replace('+', '') await this.vendor.sendMessage(number, {
await this.sock.sendMessage(`${numberClean}@c.us`, {
image: { url: imageUrl }, image: { url: imageUrl },
}) })
} }
/** /**
* * @alpha
* @param {string} number * @param {string} number
* @param {string} message * @param {string} message
* @param {boolean} voiceNote optional * @param {boolean} voiceNote optional
* @example await sendMessage('+51925465621', 'audio.mp3') * @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
*/ */
async sendAudio(number, audioUrl, voiceNote = false) { sendAudio = async (number, audioUrl, voiceNote = false) => {
const numberClean = number.replace('+', '') const numberClean = number.replace('+', '')
await this.sock.sendMessage(`${numberClean}@c.us`, { await this.vendor.sendMessage(`${numberClean}@c.us`, {
audio: { url: audioUrl }, audio: { url: audioUrl },
ptt: voiceNote, ptt: voiceNote,
}) })
} }
/**
*
* @param {string} number
* @param {string} message
* @returns
*/
sendText = async (number, message) => {
return this.vendor.sendMessage(number, { text: message })
}
/**
* TODO: Necesita terminar de implementar el sendMedia y sendButton guiarse:
* https://github.com/leifermendez/bot-whatsapp/blob/4e0fcbd8347f8a430adb43351b5415098a5d10df/packages/provider/src/web-whatsapp/index.js#L165
* @param {string} number
* @param {string} message
* @example await sendMessage('+XXXXXXXXXXX', 'Hello World')
*/
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)
return this.sendText(number, message)
}
} }
module.exports = BaileysProvider

View File

@@ -0,0 +1,21 @@
const { createWriteStream } = require('fs')
const qr = require('qr-image')
const baileyCleanNumber = (number, full = false) => {
number = number.replace('@s.whatsapp.net', '')
number = !full ? `${number}@s.whatsapp.net` : `${number}`
return number
}
const baileyGenerateImage = (base64) => {
let qr_svg = qr.image(base64, { type: 'png', margin: 4 })
qr_svg.pipe(createWriteStream(`${process.cwd()}/qr.png`))
}
const baileyIsValidNumber = (rawNumber) => {
const regexGroup = /\@g.us\b/gm
const exist = rawNumber.match(regexGroup)
return !exist
}
module.exports = { baileyCleanNumber, baileyGenerateImage, baileyIsValidNumber }

View File

@@ -4,7 +4,7 @@ const {
venomCleanNumber, venomCleanNumber,
venomGenerateImage, venomGenerateImage,
venomisValidNumber, venomisValidNumber,
} = require('./utils/utils') } = require('./utils')
/** /**
* ⚙️ VenomProvider: Es una clase tipo adaptor * ⚙️ VenomProvider: Es una clase tipo adaptor
@@ -13,7 +13,6 @@ const {
*/ */
class VenomProvider extends ProviderClass { class VenomProvider extends ProviderClass {
vendor vendor
constructor() { constructor() {
super() super()
this.init().then(() => this.initBusEvents()) this.init().then(() => this.initBusEvents())

View File

@@ -3,10 +3,10 @@ const { ProviderClass } = require('@bot-whatsapp/bot')
const { Console } = require('console') const { Console } = require('console')
const { createWriteStream } = require('fs') const { createWriteStream } = require('fs')
const { const {
cleanNumber, wwebCleanNumber,
generateImage, wwebDownloadMedia,
isValidNumber, wwebGenerateImage,
downloadMedia, wwebIsValidNumber,
} = require('./utils') } = require('./utils')
const logger = new Console({ const logger = new Console({
@@ -65,7 +65,7 @@ class WebWhatsappProvider extends ProviderClass {
`Necesitas ayuda: https://link.codigoencasa.com/DISCORD`, `Necesitas ayuda: https://link.codigoencasa.com/DISCORD`,
], ],
}) })
generateImage(qr) wwebGenerateImage(qr)
}, },
}, },
{ {
@@ -79,10 +79,10 @@ class WebWhatsappProvider extends ProviderClass {
return return
} }
if (!isValidNumber(payload.from)) { if (!wwebIsValidNumber(payload.from)) {
return return
} }
payload.from = cleanNumber(payload.from, true) payload.from = wwebCleanNumber(payload.from, true)
this.emit('message', payload) this.emit('message', payload)
}, },
}, },
@@ -98,7 +98,7 @@ class WebWhatsappProvider extends ProviderClass {
*/ */
sendMedia = async (number, mediaInput = null) => { sendMedia = async (number, mediaInput = null) => {
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`) if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
const fileDownloaded = await downloadMedia(mediaInput) const fileDownloaded = await wwebDownloadMedia(mediaInput)
const media = MessageMedia.fromFilePath(fileDownloaded) const media = MessageMedia.fromFilePath(fileDownloaded)
return this.vendor.sendMessage(number, media, { return this.vendor.sendMessage(number, media, {
sendAudioAsVoice: true, sendAudioAsVoice: true,
@@ -163,7 +163,7 @@ class WebWhatsappProvider extends ProviderClass {
* @returns * @returns
*/ */
sendMessage = async (userId, message, { options }) => { sendMessage = async (userId, message, { options }) => {
const number = cleanNumber(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)

View File

@@ -4,18 +4,18 @@ const { tmpdir } = require('os')
const http = require('http') const http = require('http')
const https = require('https') const https = require('https')
const cleanNumber = (number, full = false) => { const wwebCleanNumber = (number, full = false) => {
number = number.replace('@c.us', '') number = number.replace('@c.us', '')
number = !full ? `${number}@c.us` : `${number}` number = !full ? `${number}@c.us` : `${number}`
return number return number
} }
const generateImage = (base64) => { const wwebGenerateImage = (base64) => {
let qr_svg = qr.image(base64, { type: 'png', margin: 4 }) let qr_svg = qr.image(base64, { type: 'png', margin: 4 })
qr_svg.pipe(createWriteStream(`${process.cwd()}/qr.svg`)) qr_svg.pipe(createWriteStream(`${process.cwd()}/qr.png`))
} }
const isValidNumber = (rawNumber) => { const wwebIsValidNumber = (rawNumber) => {
const regexGroup = /\@g.us\b/gm const regexGroup = /\@g.us\b/gm
const exist = rawNumber.match(regexGroup) const exist = rawNumber.match(regexGroup)
return !exist return !exist
@@ -27,7 +27,7 @@ const isValidNumber = (rawNumber) => {
* @param {*} url * @param {*} url
* @returns * @returns
*/ */
const downloadMedia = (url) => { const wwebDownloadMedia = (url) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const ext = url.split('.').pop() const ext = url.split('.').pop()
const checkProtocol = url.includes('https:') const checkProtocol = url.includes('https:')
@@ -50,4 +50,9 @@ const downloadMedia = (url) => {
}) })
} }
module.exports = { cleanNumber, generateImage, isValidNumber, downloadMedia } module.exports = {
wwebCleanNumber,
wwebGenerateImage,
wwebIsValidNumber,
wwebDownloadMedia,
}