Merge branch 'fix/send-media-all' into 545-cuando-se-activa-fallback-dentro-de-un-addanswer-con-capture-true-no-espera-el-capture-true-y-se-salta-al-siguiente-addanswer

This commit is contained in:
Leifer Mendez
2023-01-28 16:44:39 +01:00
9 changed files with 270 additions and 77 deletions

View File

@@ -81,6 +81,7 @@
"fs-extra": "^11.1.0", "fs-extra": "^11.1.0",
"git-cz": "^4.9.0", "git-cz": "^4.9.0",
"husky": "^8.0.2", "husky": "^8.0.2",
"mime-types": "^2.1.35",
"only-allow": "^1.1.1", "only-allow": "^1.1.1",
"prettier": "^2.8.0", "prettier": "^2.8.0",
"pretty-quick": "^3.1.3", "pretty-quick": "^3.1.3",

View File

@@ -0,0 +1,65 @@
const mimeDep = require('mime-types')
const { tmpdir } = require('os')
const http = require('http')
const https = require('https')
const { rename, createWriteStream } = require('fs')
/**
* Extrar el mimetype from buffer
* @param {string} response
* @returns
*/
const fileTypeFromFile = async (response) => {
const type = response.headers['content-type'] ?? null
const ext = mimeDep.extension(type)
return {
type,
ext,
}
}
/**
* Descargar archivo binay en tmp
* @param {*} url
* @returns
*/
const generalDownload = async (url) => {
const handleDownload = () => {
const checkProtocol = url.includes('https:')
const handleHttp = checkProtocol ? https : http
const name = `tmp-${Date.now()}-dat`
const fullPath = `${tmpdir()}/${name}`
const file = createWriteStream(fullPath)
return new Promise((res, rej) => {
handleHttp.get(url, function (response) {
response.pipe(file)
file.on('finish', async function () {
file.close()
res({ response, fullPath })
})
file.on('error', function () {
file.close()
rej(null)
})
})
})
}
const handleFile = (pathInput, ext) =>
new Promise((resolve, reject) => {
const fullPath = `${pathInput}.${ext}`
rename(pathInput, fullPath, (err) => {
if (err) reject(null)
resolve(fullPath)
})
})
const httpResponse = await handleDownload()
const { ext } = await fileTypeFromFile(httpResponse.response)
const getPath = await handleFile(httpResponse.fullPath, ext)
return getPath
}
module.exports = { generalDownload }

View File

@@ -4,7 +4,7 @@ const pino = require('pino')
const rimraf = require('rimraf') const rimraf = require('rimraf')
const mime = require('mime-types') const mime = require('mime-types')
const { join } = require('path') const { join } = require('path')
const { existsSync, createWriteStream, readFileSync } = require('fs') const { createWriteStream, readFileSync } = require('fs')
const { Console } = require('console') const { Console } = require('console')
const { const {
@@ -13,13 +13,15 @@ const {
Browsers, Browsers,
DisconnectReason, DisconnectReason,
} = require('@adiwajshing/baileys') } = require('@adiwajshing/baileys')
const { const {
baileyGenerateImage, baileyGenerateImage,
baileyCleanNumber, baileyCleanNumber,
baileyIsValidNumber, baileyIsValidNumber,
baileyDownloadMedia,
} = require('./utils') } = require('./utils')
const { generalDownload } = require('../../common/download')
const logger = new Console({ const logger = new Console({
stdout: createWriteStream(`${process.cwd()}/baileys.log`), stdout: createWriteStream(`${process.cwd()}/baileys.log`),
}) })
@@ -169,14 +171,50 @@ class BaileysProvider extends ProviderClass {
*/ */
sendMedia = async (number, imageUrl, text) => { sendMedia = async (number, imageUrl, text) => {
const fileDownloaded = await baileyDownloadMedia(imageUrl) 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)
return this.sendFile(number, fileDownloaded)
}
/**
* Enviar imagen
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendImage = async (number, filePath, text) => {
return this.vendor.sendMessage(number, { return this.vendor.sendMessage(number, {
image: readFileSync(fileDownloaded), image: readFileSync(filePath),
caption: text, caption: text,
}) })
} }
/** /**
* Enviar video
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendVideo = async (number, filePath, text) => {
return this.vendor.sendMessage(number, {
video: readFileSync(filePath),
caption: text,
gifPlayback: true,
})
}
/**
* Enviar audio
* @alpha * @alpha
* @param {string} number * @param {string} number
* @param {string} message * @param {string} message
@@ -185,8 +223,7 @@ class BaileysProvider extends ProviderClass {
*/ */
sendAudio = async (number, audioUrl, voiceNote = false) => { sendAudio = async (number, audioUrl, voiceNote = false) => {
const numberClean = number.replace('+', '') return this.vendor.sendMessage(number, {
await this.vendor.sendMessage(`${numberClean}@c.us`, {
audio: { url: audioUrl }, audio: { url: audioUrl },
ptt: voiceNote, ptt: voiceNote,
}) })
@@ -210,17 +247,13 @@ class BaileysProvider extends ProviderClass {
*/ */
sendFile = async (number, filePath) => { sendFile = async (number, filePath) => {
if (existsSync(filePath)) { const mimeType = mime.lookup(filePath)
const mimeType = mime.lookup(filePath) const fileName = filePath.split('/').pop()
const numberClean = number.replace('+', '') return this.vendor.sendMessage(number, {
const fileName = filePath.split('/').pop() document: { url: filePath },
mimetype: mimeType,
await this.vendor.sendMessage(`${numberClean}@c.us`, { fileName: fileName,
document: { url: filePath }, })
mimetype: mimeType,
fileName: fileName,
})
}
} }
/** /**

View File

@@ -1,7 +1,6 @@
{ {
"dependencies": { "dependencies": {
"@adiwajshing/baileys": "4.4.0", "@adiwajshing/baileys": "4.4.0",
"mime-types": "2.1.35",
"wa-sticker-formatter": "4.3.2" "wa-sticker-formatter": "4.3.2"
} }
} }

View File

@@ -1,9 +1,6 @@
const { createWriteStream } = require('fs') const { createWriteStream } = require('fs')
const combineImage = require('combine-image') const combineImage = require('combine-image')
const qr = require('qr-image') const qr = require('qr-image')
const { tmpdir } = require('os')
const http = require('http')
const https = require('https')
const baileyCleanNumber = (number, full = false) => { const baileyCleanNumber = (number, full = false) => {
number = number.replace('@s.whatsapp.net', '') number = number.replace('@s.whatsapp.net', '')
@@ -41,38 +38,8 @@ const baileyIsValidNumber = (rawNumber) => {
return !exist return !exist
} }
/**
* 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 = { module.exports = {
baileyCleanNumber, baileyCleanNumber,
baileyGenerateImage, baileyGenerateImage,
baileyIsValidNumber, baileyIsValidNumber,
baileyDownloadMedia,
} }

View File

@@ -2,18 +2,20 @@ const { ProviderClass } = require('@bot-whatsapp/bot')
const venom = require('venom-bot') const venom = require('venom-bot')
const { createWriteStream } = require('fs') const { createWriteStream } = require('fs')
const { Console } = require('console') const { Console } = require('console')
const mime = require('mime-types')
const { const {
venomCleanNumber, venomCleanNumber,
venomGenerateImage, venomGenerateImage,
venomisValidNumber, venomisValidNumber,
venomDownloadMedia,
} = require('./utils') } = require('./utils')
const logger = new Console({ const logger = new Console({
stdout: createWriteStream(`${process.cwd()}/venom.log`), stdout: createWriteStream(`${process.cwd()}/venom.log`),
}) })
const { generalDownload } = require('../../common/download')
/** /**
* ⚙️ VenomProvider: Es una clase tipo adaptor * ⚙️ VenomProvider: Es una clase tipo adaptor
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas) * que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
@@ -134,6 +136,53 @@ class VenomProvider extends ProviderClass {
// return this.vendor.sendButtons(number, "Title", buttons1, "Description"); // return this.vendor.sendButtons(number, "Title", buttons1, "Description");
} }
/**
* Enviar audio
* @alpha
* @param {string} number
* @param {string} message
* @param {boolean} voiceNote optional
* @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3')
*/
sendAudio = async (number, audioPath) => {
return this.vendor.sendVoice(number, audioPath)
}
/**
* Enviar imagen
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendImage = async (number, filePath, text) => {
return this.vendor.sendImage(number, filePath, 'image-name', text)
}
/**
*
* @param {string} number
* @param {string} filePath
* @example await sendMessage('+XXXXXXXXXXX', './document/file.pdf')
*/
sendFile = async (number, filePath, text) => {
const fileName = filePath.split('/').pop()
return this.vendor.sendFile(number, filePath, fileName, text)
}
/**
* Enviar video
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendVideo = async (number, filePath, text) => {
return this.vendor.sendVideoAsGif(number, filePath, 'video.gif', text)
}
/** /**
* Enviar imagen o multimedia * Enviar imagen o multimedia
* @param {*} number * @param {*} number
@@ -141,10 +190,18 @@ class VenomProvider extends ProviderClass {
* @param {*} message * @param {*} message
* @returns * @returns
*/ */
sendMedia = async (number, mediaInput, message) => { sendMedia = async (number, mediaUrl, text) => {
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`) const fileDownloaded = await generalDownload(mediaUrl)
const fileDownloaded = await venomDownloadMedia(mediaInput) const mimeType = mime.lookup(fileDownloaded)
return this.vendor.sendImage(number, fileDownloaded, '.', message)
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)
return this.sendFile(number, fileDownloaded, text)
} }
/** /**

View File

@@ -1,10 +1,9 @@
const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js') 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 } = require('fs') const { createWriteStream, readFileSync } = require('fs')
const { const {
wwebCleanNumber, wwebCleanNumber,
wwebDownloadMedia,
wwebGenerateImage, wwebGenerateImage,
wwebIsValidNumber, wwebIsValidNumber,
} = require('./utils') } = require('./utils')
@@ -13,6 +12,9 @@ const logger = new Console({
stdout: createWriteStream('./log'), stdout: createWriteStream('./log'),
}) })
const { generalDownload } = require('../../common/download')
const mime = require('mime-types')
/** /**
* ⚙️ WebWhatsappProvider: Es una clase tipo adaptor * ⚙️ WebWhatsappProvider: Es una clase tipo adaptor
* que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas) * que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas)
@@ -35,6 +37,7 @@ class WebWhatsappProvider extends ProviderClass {
'--disable-setuid-sandbox', '--disable-setuid-sandbox',
'--unhandled-rejections=strict', '--unhandled-rejections=strict',
], ],
//executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
}, },
}) })
@@ -103,23 +106,6 @@ class WebWhatsappProvider extends ProviderClass {
}, },
] ]
/**
* Enviar un archivo multimedia
* https://docs.wwebjs.dev/MessageMedia.html
* @private
* @param {*} number
* @param {*} mediaInput
* @returns
*/
sendMedia = async (number, mediaInput = null) => {
if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`)
const fileDownloaded = await wwebDownloadMedia(mediaInput)
const media = MessageMedia.fromFilePath(fileDownloaded)
return this.vendor.sendMessage(number, media, {
sendAudioAsVoice: true,
})
}
/** /**
* Enviar botones * Enviar botones
* https://docs.wwebjs.dev/Buttons.html * https://docs.wwebjs.dev/Buttons.html
@@ -170,6 +156,90 @@ class WebWhatsappProvider extends ProviderClass {
return this.vendor.sendMessage(number, message) return this.vendor.sendMessage(number, message)
} }
/**
* Enviar imagen
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendImage = async (number, filePath) => {
const base64 = readFileSync(filePath, { encoding: 'base64' })
const mimeType = mime.lookup(filePath)
const media = new MessageMedia(mimeType, base64)
return this.vendor.sendMessage(number, media, {
caption: 'soy una imagen',
})
}
/**
* Enviar audio
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendAudio = async (number, filePath) => {
const base64 = readFileSync(filePath, { encoding: 'base64' })
const mimeType = mime.lookup(filePath)
const media = new MessageMedia(mimeType, base64)
return this.vendor.sendMessage(number, media, {
caption: 'soy un audio',
})
}
/**
* Enviar video
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendVideo = async (number, filePath) => {
const base64 = readFileSync(filePath, { encoding: 'base64' })
const mimeType = mime.lookup(filePath)
const media = new MessageMedia(mimeType, base64)
return this.vendor.sendMessage(number, media, {
sendMediaAsDocument: true,
})
}
/**
* Enviar Arhivos/pdf
* @param {*} number
* @param {*} imageUrl
* @param {*} text
* @returns
*/
sendFile = async (number, filePath) => {
const base64 = readFileSync(filePath, { encoding: 'base64' })
const mimeType = mime.lookup(filePath)
const media = new MessageMedia(mimeType, base64)
return this.vendor.sendMessage(number, media)
}
/**
* Enviar imagen o multimedia
* @param {*} number
* @param {*} mediaInput
* @param {*} message
* @returns
*/
sendMedia = async (number, mediaUrl, text) => {
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)
return this.sendFile(number, fileDownloaded)
}
/** /**
* *
* @param {*} userId * @param {*} userId

View File

@@ -1,5 +1,5 @@
{ {
"dependencies": { "dependencies": {
"whatsapp-web.js": "1.19.2" "whatsapp-web.js": "1.19.3"
} }
} }

View File

@@ -1113,6 +1113,7 @@ __metadata:
fs-extra: ^11.1.0 fs-extra: ^11.1.0
git-cz: ^4.9.0 git-cz: ^4.9.0
husky: ^8.0.2 husky: ^8.0.2
mime-types: ^2.1.35
only-allow: ^1.1.1 only-allow: ^1.1.1
prettier: ^2.8.0 prettier: ^2.8.0
pretty-quick: ^3.1.3 pretty-quick: ^3.1.3
@@ -13443,7 +13444,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mime-types@npm:^2.1.12, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": "mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
version: 2.1.35 version: 2.1.35
resolution: "mime-types@npm:2.1.35" resolution: "mime-types@npm:2.1.35"
dependencies: dependencies: