From eab39e4ac06fd46f1a4671f8c15d1456b4400b97 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Tue, 24 Jan 2023 16:54:31 +0100 Subject: [PATCH 01/11] feat: :fire: bailey add media --- package.json | 2 + packages/provider/common/fileType.js | 16 ++++++ packages/provider/src/baileys/index.js | 42 ++++++++++++++- packages/provider/src/baileys/package.json | 1 - packages/provider/src/baileys/utils.js | 50 ++++++++++++------ yarn.lock | 61 ++++++++++++++++++++-- 6 files changed, 149 insertions(+), 23 deletions(-) create mode 100644 packages/provider/common/fileType.js diff --git a/package.json b/package.json index 2d1061e..3f7f729 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,9 @@ "eslint-config-prettier": "^8.5.0", "fs-extra": "^11.1.0", "git-cz": "^4.9.0", + "got": "11.8.3", "husky": "^8.0.2", + "mime-types": "^2.1.35", "only-allow": "^1.1.1", "prettier": "^2.8.0", "pretty-quick": "^3.1.3", diff --git a/packages/provider/common/fileType.js b/packages/provider/common/fileType.js new file mode 100644 index 0000000..3521e61 --- /dev/null +++ b/packages/provider/common/fileType.js @@ -0,0 +1,16 @@ +const mimeDep = require('mime-types') +/** + * 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, + } +} + +module.exports = { fileTypeFromFile } diff --git a/packages/provider/src/baileys/index.js b/packages/provider/src/baileys/index.js index de6c66d..b12d094 100644 --- a/packages/provider/src/baileys/index.js +++ b/packages/provider/src/baileys/index.js @@ -170,12 +170,51 @@ class BaileysProvider extends ProviderClass { sendMedia = async (number, imageUrl, text) => { const fileDownloaded = await baileyDownloadMedia(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) + + console.log(mimeType) return this.vendor.sendMessage(number, { image: readFileSync(fileDownloaded), caption: text, }) } + /** + * + * @param {*} number + * @param {*} imageUrl + * @param {*} text + * @returns + */ + sendImage = async (number, filePath, text) => { + return this.vendor.sendMessage(number, { + image: readFileSync(filePath), + caption: text, + }) + } + + /** + * + * @param {*} number + * @param {*} imageUrl + * @param {*} text + * @returns + */ + sendVideo = async (number, filePath, text) => { + return this.vendor.sendMessage(number, { + video: readFileSync(filePath), + caption: text, + gifPlayback: true, + }) + } + /** * @alpha * @param {string} number @@ -185,8 +224,7 @@ class BaileysProvider extends ProviderClass { */ sendAudio = async (number, audioUrl, voiceNote = false) => { - const numberClean = number.replace('+', '') - await this.vendor.sendMessage(`${numberClean}@c.us`, { + await this.vendor.sendMessage(number, { audio: { url: audioUrl }, ptt: voiceNote, }) diff --git a/packages/provider/src/baileys/package.json b/packages/provider/src/baileys/package.json index da529d3..918a8e9 100644 --- a/packages/provider/src/baileys/package.json +++ b/packages/provider/src/baileys/package.json @@ -1,7 +1,6 @@ { "dependencies": { "@adiwajshing/baileys": "4.4.0", - "mime-types": "2.1.35", "wa-sticker-formatter": "4.3.2" } } diff --git a/packages/provider/src/baileys/utils.js b/packages/provider/src/baileys/utils.js index 433ddee..22c36a7 100644 --- a/packages/provider/src/baileys/utils.js +++ b/packages/provider/src/baileys/utils.js @@ -1,10 +1,12 @@ -const { createWriteStream } = require('fs') +const { createWriteStream, rename } = 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 { fileTypeFromFile } = require('../../common/fileType') + const baileyCleanNumber = (number, full = false) => { number = number.replace('@s.whatsapp.net', '') number = !full ? `${number}@s.whatsapp.net` : `${number}` @@ -47,27 +49,43 @@ const baileyIsValidNumber = (rawNumber) => { * @param {*} url * @returns */ -const baileyDownloadMedia = (url) => { - return new Promise((resolve, reject) => { - const ext = url.split('.').pop() +const baileyDownloadMedia = async (url) => { + const handleDownload = () => { const checkProtocol = url.includes('https:') const handleHttp = checkProtocol ? https : http - const name = `tmp-${Date.now()}.${ext}` + const name = `tmp-${Date.now()}-dat` 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) + + 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 = { diff --git a/yarn.lock b/yarn.lock index cf802d5..4b1ffb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1112,7 +1112,10 @@ __metadata: eslint-config-prettier: ^8.5.0 fs-extra: ^11.1.0 git-cz: ^4.9.0 + got: 11.8.3 husky: ^8.0.2 + mime-types: ^2.1.35 + name2mime: ^1.0.1 only-allow: ^1.1.1 prettier: ^2.8.0 pretty-quick: ^3.1.3 @@ -2933,6 +2936,13 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/is@npm:^4.0.0": + version: 4.6.0 + resolution: "@sindresorhus/is@npm:4.6.0" + checksum: 83839f13da2c29d55c97abc3bc2c55b250d33a0447554997a85c539e058e57b8da092da396e252b11ec24a0279a0bed1f537fa26302209327060643e327f81d2 + languageName: node + linkType: hard + "@sindresorhus/is@npm:^5.2.0": version: 5.3.0 resolution: "@sindresorhus/is@npm:5.3.0" @@ -2977,7 +2987,7 @@ __metadata: languageName: node linkType: hard -"@szmarczak/http-timer@npm:^4.0.0": +"@szmarczak/http-timer@npm:^4.0.0, @szmarczak/http-timer@npm:^4.0.5": version: 4.0.6 resolution: "@szmarczak/http-timer@npm:4.0.6" dependencies: @@ -5073,6 +5083,13 @@ __metadata: languageName: node linkType: hard +"cacheable-lookup@npm:^5.0.3": + version: 5.0.4 + resolution: "cacheable-lookup@npm:5.0.4" + checksum: 763e02cf9196bc9afccacd8c418d942fc2677f22261969a4c2c2e760fa44a2351a81557bd908291c3921fe9beb10b976ba8fa50c5ca837c5a0dd945f16468f2d + languageName: node + linkType: hard + "cacheable-lookup@npm:^7.0.0": version: 7.0.0 resolution: "cacheable-lookup@npm:7.0.0" @@ -5125,7 +5142,7 @@ __metadata: languageName: node linkType: hard -"cacheable-request@npm:^7.0.1": +"cacheable-request@npm:^7.0.1, cacheable-request@npm:^7.0.2": version: 7.0.2 resolution: "cacheable-request@npm:7.0.2" dependencies: @@ -9899,6 +9916,25 @@ __metadata: languageName: node linkType: hard +"got@npm:11.8.3": + version: 11.8.3 + resolution: "got@npm:11.8.3" + dependencies: + "@sindresorhus/is": ^4.0.0 + "@szmarczak/http-timer": ^4.0.5 + "@types/cacheable-request": ^6.0.1 + "@types/responselike": ^1.0.0 + cacheable-lookup: ^5.0.3 + cacheable-request: ^7.0.2 + decompress-response: ^6.0.0 + http2-wrapper: ^1.0.0-beta.5.2 + lowercase-keys: ^2.0.0 + p-cancelable: ^2.0.0 + responselike: ^2.0.0 + checksum: 3b6db107d9765470b18e4cb22f7c7400381be7425b9be5823f0168d6c21b5d6b28b023c0b3ee208f73f6638c3ce251948ca9b54a1e8f936d3691139ac202d01b + languageName: node + linkType: hard + "got@npm:^10.0.0, got@npm:^10.7.0": version: 10.7.0 resolution: "got@npm:10.7.0" @@ -10446,6 +10482,16 @@ __metadata: languageName: node linkType: hard +"http2-wrapper@npm:^1.0.0-beta.5.2": + version: 1.0.3 + resolution: "http2-wrapper@npm:1.0.3" + dependencies: + quick-lru: ^5.1.1 + resolve-alpn: ^1.0.0 + checksum: 74160b862ec699e3f859739101ff592d52ce1cb207b7950295bf7962e4aa1597ef709b4292c673bece9c9b300efad0559fc86c71b1409c7a1e02b7229456003e + languageName: node + linkType: hard + "http2-wrapper@npm:^2.1.10": version: 2.2.0 resolution: "http2-wrapper@npm:2.2.0" @@ -13443,7 +13489,7 @@ __metadata: languageName: node 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 resolution: "mime-types@npm:2.1.35" dependencies: @@ -13839,6 +13885,13 @@ __metadata: languageName: node linkType: hard +"name2mime@npm:^1.0.1": + version: 1.0.1 + resolution: "name2mime@npm:1.0.1" + checksum: 46630096d2a5c381231f5e5025d3aaef824b5db29677971b8a93f565e63979524d6f43457dd4b93591341c26af2abb44ef7aa87943c51d2eed60b94519815880 + languageName: node + linkType: hard + "named-placeholders@npm:^1.1.2": version: 1.1.2 resolution: "named-placeholders@npm:1.1.2" @@ -16820,7 +16873,7 @@ __metadata: languageName: node linkType: hard -"resolve-alpn@npm:^1.2.0": +"resolve-alpn@npm:^1.0.0, resolve-alpn@npm:^1.2.0": version: 1.2.1 resolution: "resolve-alpn@npm:1.2.1" checksum: f558071fcb2c60b04054c99aebd572a2af97ef64128d59bef7ab73bd50d896a222a056de40ffc545b633d99b304c259ea9d0c06830d5c867c34f0bfa60b8eae0 From e19c3a25a40259c74b4add9635af4844907eed26 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Tue, 24 Jan 2023 19:43:11 +0100 Subject: [PATCH 02/11] feat: :zap: more feature --- packages/provider/src/baileys/index.js | 32 +++++++++++--------------- yarn.lock | 8 ------- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/packages/provider/src/baileys/index.js b/packages/provider/src/baileys/index.js index b12d094..4bc0a03 100644 --- a/packages/provider/src/baileys/index.js +++ b/packages/provider/src/baileys/index.js @@ -13,6 +13,7 @@ const { Browsers, DisconnectReason, } = require('@adiwajshing/baileys') + const { baileyGenerateImage, baileyCleanNumber, @@ -179,15 +180,11 @@ class BaileysProvider extends ProviderClass { if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded, text) - console.log(mimeType) - return this.vendor.sendMessage(number, { - image: readFileSync(fileDownloaded), - caption: text, - }) + return this.sendFile() } /** - * + * Enviar imagen * @param {*} number * @param {*} imageUrl * @param {*} text @@ -201,7 +198,7 @@ class BaileysProvider extends ProviderClass { } /** - * + * Enviar video * @param {*} number * @param {*} imageUrl * @param {*} text @@ -216,6 +213,7 @@ class BaileysProvider extends ProviderClass { } /** + * Enviar audio * @alpha * @param {string} number * @param {string} message @@ -224,7 +222,7 @@ class BaileysProvider extends ProviderClass { */ sendAudio = async (number, audioUrl, voiceNote = false) => { - await this.vendor.sendMessage(number, { + return this.vendor.sendMessage(number, { audio: { url: audioUrl }, ptt: voiceNote, }) @@ -248,17 +246,13 @@ class BaileysProvider extends ProviderClass { */ sendFile = async (number, filePath) => { - if (existsSync(filePath)) { - const mimeType = mime.lookup(filePath) - const numberClean = number.replace('+', '') - const fileName = filePath.split('/').pop() - - await this.vendor.sendMessage(`${numberClean}@c.us`, { - document: { url: filePath }, - mimetype: mimeType, - fileName: fileName, - }) - } + const mimeType = mime.lookup(filePath) + const fileName = filePath.split('/').pop() + return this.vendor.sendMessage(number, { + document: { url: filePath }, + mimetype: mimeType, + fileName: fileName, + }) } /** diff --git a/yarn.lock b/yarn.lock index 4b1ffb6..c99a8c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1115,7 +1115,6 @@ __metadata: got: 11.8.3 husky: ^8.0.2 mime-types: ^2.1.35 - name2mime: ^1.0.1 only-allow: ^1.1.1 prettier: ^2.8.0 pretty-quick: ^3.1.3 @@ -13885,13 +13884,6 @@ __metadata: languageName: node linkType: hard -"name2mime@npm:^1.0.1": - version: 1.0.1 - resolution: "name2mime@npm:1.0.1" - checksum: 46630096d2a5c381231f5e5025d3aaef824b5db29677971b8a93f565e63979524d6f43457dd4b93591341c26af2abb44ef7aa87943c51d2eed60b94519815880 - languageName: node - linkType: hard - "named-placeholders@npm:^1.1.2": version: 1.1.2 resolution: "named-placeholders@npm:1.1.2" From 14d1a61fa259c09135c37c55bd79e97c9c8367e4 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Tue, 24 Jan 2023 22:14:55 +0100 Subject: [PATCH 03/11] feat(provider): :zap: bailey add send file video audio --- packages/provider/common/download.js | 65 ++++++++++++++++++++++++++ packages/provider/common/fileType.js | 16 ------- packages/provider/src/baileys/index.js | 9 ++-- packages/provider/src/baileys/utils.js | 53 +-------------------- 4 files changed, 71 insertions(+), 72 deletions(-) create mode 100644 packages/provider/common/download.js delete mode 100644 packages/provider/common/fileType.js diff --git a/packages/provider/common/download.js b/packages/provider/common/download.js new file mode 100644 index 0000000..76e23a0 --- /dev/null +++ b/packages/provider/common/download.js @@ -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 } diff --git a/packages/provider/common/fileType.js b/packages/provider/common/fileType.js deleted file mode 100644 index 3521e61..0000000 --- a/packages/provider/common/fileType.js +++ /dev/null @@ -1,16 +0,0 @@ -const mimeDep = require('mime-types') -/** - * 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, - } -} - -module.exports = { fileTypeFromFile } diff --git a/packages/provider/src/baileys/index.js b/packages/provider/src/baileys/index.js index 4bc0a03..9361731 100644 --- a/packages/provider/src/baileys/index.js +++ b/packages/provider/src/baileys/index.js @@ -4,7 +4,7 @@ const pino = require('pino') const rimraf = require('rimraf') const mime = require('mime-types') const { join } = require('path') -const { existsSync, createWriteStream, readFileSync } = require('fs') +const { createWriteStream, readFileSync } = require('fs') const { Console } = require('console') const { @@ -18,9 +18,10 @@ const { baileyGenerateImage, baileyCleanNumber, baileyIsValidNumber, - baileyDownloadMedia, } = require('./utils') +const { generalDownload } = require('../../common/download') + const logger = new Console({ stdout: createWriteStream(`${process.cwd()}/baileys.log`), }) @@ -170,7 +171,7 @@ class BaileysProvider extends ProviderClass { */ sendMedia = async (number, imageUrl, text) => { - const fileDownloaded = await baileyDownloadMedia(imageUrl) + const fileDownloaded = await generalDownload(imageUrl) const mimeType = mime.lookup(fileDownloaded) if (mimeType.includes('image')) @@ -180,7 +181,7 @@ class BaileysProvider extends ProviderClass { if (mimeType.includes('audio')) return this.sendAudio(number, fileDownloaded, text) - return this.sendFile() + return this.sendFile(number, fileDownloaded) } /** diff --git a/packages/provider/src/baileys/utils.js b/packages/provider/src/baileys/utils.js index 22c36a7..0b2a886 100644 --- a/packages/provider/src/baileys/utils.js +++ b/packages/provider/src/baileys/utils.js @@ -1,11 +1,6 @@ -const { createWriteStream, rename } = require('fs') +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 { fileTypeFromFile } = require('../../common/fileType') const baileyCleanNumber = (number, full = false) => { number = number.replace('@s.whatsapp.net', '') @@ -43,54 +38,8 @@ const baileyIsValidNumber = (rawNumber) => { return !exist } -/** - * Incompleta - * Descargar archivo multimedia para enviar - * @param {*} url - * @returns - */ -const baileyDownloadMedia = 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 = { baileyCleanNumber, baileyGenerateImage, baileyIsValidNumber, - baileyDownloadMedia, } From 9dd7c02b6a5474aff063f7d6be0ca8519504b93c Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Wed, 25 Jan 2023 16:10:13 -0500 Subject: [PATCH 04/11] feat(provider): :rocket: implements all send media to venom provider --- packages/provider/src/venom/index.js | 67 +++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/packages/provider/src/venom/index.js b/packages/provider/src/venom/index.js index 4b7c231..10fe5aa 100644 --- a/packages/provider/src/venom/index.js +++ b/packages/provider/src/venom/index.js @@ -2,18 +2,20 @@ const { ProviderClass } = require('@bot-whatsapp/bot') const venom = require('venom-bot') const { createWriteStream } = require('fs') const { Console } = require('console') +const mime = require('mime-types') const { venomCleanNumber, venomGenerateImage, venomisValidNumber, - venomDownloadMedia, } = require('./utils') const logger = new Console({ stdout: createWriteStream(`${process.cwd()}/venom.log`), }) +const { generalDownload } = require('../../common/download') + /** * ⚙️ VenomProvider: Es una clase tipo adaptor * 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"); } + /** + * Enviar audio + * @alpha + * @param {string} number + * @param {string} message + * @param {boolean} voiceNote optional + * @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3') + */ + + sendAudio = async (number, audioPath, voiceNote = false) => { + 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 * @param {*} number @@ -141,10 +190,18 @@ class VenomProvider extends ProviderClass { * @param {*} message * @returns */ - sendMedia = async (number, mediaInput, message) => { - if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`) - const fileDownloaded = await venomDownloadMedia(mediaInput) - return this.vendor.sendImage(number, fileDownloaded, '.', message) + 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, text) + if (mimeType.includes('audio')) + return this.sendAudio(number, fileDownloaded) + + return this.sendFile(number, fileDownloaded, text) } /** From 6ff1a3a980196c01c66ed04ee07d0e7e57256504 Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Fri, 27 Jan 2023 12:51:15 -0500 Subject: [PATCH 05/11] feat(provider): :rocket: send file wwebjs --- packages/provider/src/web-whatsapp/index.js | 122 +++++++++++++++++--- 1 file changed, 104 insertions(+), 18 deletions(-) diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index f7f8bd0..2709960 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -1,7 +1,7 @@ const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js') const { ProviderClass } = require('@bot-whatsapp/bot') const { Console } = require('console') -const { createWriteStream } = require('fs') +const { createWriteStream, readFileSync } = require('fs') const { wwebCleanNumber, wwebDownloadMedia, @@ -13,6 +13,9 @@ const logger = new Console({ stdout: createWriteStream('./log'), }) +const { generalDownload } = require('../../common/download') +const mime = require('mime-types') + /** * ⚙️ WebWhatsappProvider: Es una clase tipo adaptor * que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas) @@ -35,6 +38,7 @@ class WebWhatsappProvider extends ProviderClass { '--disable-setuid-sandbox', '--unhandled-rejections=strict', ], + //executablePath: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', }, }) @@ -103,23 +107,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 * https://docs.wwebjs.dev/Buttons.html @@ -170,6 +157,105 @@ class WebWhatsappProvider extends ProviderClass { return this.vendor.sendMessage(number, message) } + /** + * Enviar imagen + * @param {*} number + * @param {*} imageUrl + * @param {*} text + * @returns + */ + sendImage = async (number, filePath, text) => { + const base64 = readFileSync(filePath, { encoding: 'base64' }) + const mimeType = mime.lookup(filePath) + const media = new MessageMedia(mimeType, base64) + return this.vendor.sendMessage(number, media, text) + } + + /** + * Enviar audio + * @param {*} number + * @param {*} imageUrl + * @param {*} text + * @returns + */ + /** + * Enviar audio + * @param {*} number + * @param {*} imageUrl + * @param {*} text + * @returns + */ + sendAudio = async (number, filePath, text) => { + const base64 = readFileSync(filePath, { encoding: 'base64' }) + const mimeType = mime.lookup(filePath) + const media = new MessageMedia(mimeType, base64) + return this.vendor.sendMessage(number, media, text) + } + /** + * Enviar audio + * @param {*} number + * @param {*} imageUrl + * @param {*} text + * @returns + */ + sendAudio = async (number, filePath, text) => { + const base64 = readFileSync(filePath, { encoding: 'base64' }) + const mimeType = mime.lookup(filePath) + const media = new MessageMedia(mimeType, base64) + return this.vendor.sendMessage(number, media, text) + } + + /** + * 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, text) => { + const base64 = readFileSync(filePath, { encoding: 'base64' }) + const mimeType = mime.lookup(filePath) + const media = new MessageMedia(mimeType, base64) + return this.vendor.sendMessage(number, media, text) + } + + /** + * 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 From cbe438b77854e8df48b9dafaf7a837d21124ac5f Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:28:25 -0500 Subject: [PATCH 06/11] feat(provider): :rocket: fix issues in providers venom and wwebjs --- packages/provider/src/venom/index.js | 2 +- packages/provider/src/web-whatsapp/index.js | 34 ++++++--------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/packages/provider/src/venom/index.js b/packages/provider/src/venom/index.js index 10fe5aa..3e1b630 100644 --- a/packages/provider/src/venom/index.js +++ b/packages/provider/src/venom/index.js @@ -145,7 +145,7 @@ class VenomProvider extends ProviderClass { * @example await sendMessage('+XXXXXXXXXXX', 'audio.mp3') */ - sendAudio = async (number, audioPath, voiceNote = false) => { + sendAudio = async (number, audioPath) => { return this.vendor.sendVoice(number, audioPath) } diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index 2709960..f66e97a 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -4,7 +4,6 @@ const { Console } = require('console') const { createWriteStream, readFileSync } = require('fs') const { wwebCleanNumber, - wwebDownloadMedia, wwebGenerateImage, wwebIsValidNumber, } = require('./utils') @@ -168,7 +167,9 @@ class WebWhatsappProvider extends ProviderClass { const base64 = readFileSync(filePath, { encoding: 'base64' }) const mimeType = mime.lookup(filePath) const media = new MessageMedia(mimeType, base64) - return this.vendor.sendMessage(number, media, text) + return this.vendor.sendMessage(number, media, { + caption: 'soy una imagen', + }) } /** @@ -178,31 +179,14 @@ class WebWhatsappProvider extends ProviderClass { * @param {*} text * @returns */ - /** - * Enviar audio - * @param {*} number - * @param {*} imageUrl - * @param {*} text - * @returns - */ + sendAudio = async (number, filePath, text) => { const base64 = readFileSync(filePath, { encoding: 'base64' }) const mimeType = mime.lookup(filePath) const media = new MessageMedia(mimeType, base64) - return this.vendor.sendMessage(number, media, text) - } - /** - * Enviar audio - * @param {*} number - * @param {*} imageUrl - * @param {*} text - * @returns - */ - sendAudio = async (number, filePath, text) => { - const base64 = readFileSync(filePath, { encoding: 'base64' }) - const mimeType = mime.lookup(filePath) - const media = new MessageMedia(mimeType, base64) - return this.vendor.sendMessage(number, media, text) + return this.vendor.sendMessage(number, media, { + caption: 'soy un audio', + }) } /** @@ -228,11 +212,11 @@ class WebWhatsappProvider extends ProviderClass { * @param {*} text * @returns */ - sendFile = async (number, filePath, text) => { + 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, text) + return this.vendor.sendMessage(number, media) } /** From dcb0566d2bc3da40cd0c71554bb5ea0ec115d9ca Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:31:05 -0500 Subject: [PATCH 07/11] feat(provider): :rocket: fix provider venom and wwebjs From b2afa45352a7ab1f5d9775f3c1fde475bd8ca204 Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:32:42 -0500 Subject: [PATCH 08/11] feat(provider): :rocket: fix provider From f8c7184487065443ab10f77aaf585e8bd63ca441 Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:42:45 -0500 Subject: [PATCH 09/11] feat(provider): :rocket: fix provider From 0ad4c58457b548dc41c0f9e8470d59c48de7b95a Mon Sep 17 00:00:00 2001 From: aurik3 <37228512+aurik3@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:51:20 -0500 Subject: [PATCH 10/11] feat(provider): :rocket: fix provider --- packages/provider/src/web-whatsapp/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index f66e97a..693d1b9 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -163,7 +163,7 @@ class WebWhatsappProvider extends ProviderClass { * @param {*} text * @returns */ - sendImage = async (number, filePath, text) => { + sendImage = async (number, filePath) => { const base64 = readFileSync(filePath, { encoding: 'base64' }) const mimeType = mime.lookup(filePath) const media = new MessageMedia(mimeType, base64) @@ -180,7 +180,7 @@ class WebWhatsappProvider extends ProviderClass { * @returns */ - sendAudio = async (number, filePath, text) => { + sendAudio = async (number, filePath) => { const base64 = readFileSync(filePath, { encoding: 'base64' }) const mimeType = mime.lookup(filePath) const media = new MessageMedia(mimeType, base64) From f95331d3dc70e76a3dfbe4c8d24059f0e7a164ef Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Sat, 28 Jan 2023 16:25:22 +0100 Subject: [PATCH 11/11] feat(provider): :zap: venom wweb --- package.json | 1 - packages/docs/src/routes/docs/flows/index.mdx | 98 +++++++++++-------- .../provider/src/web-whatsapp/package.json | 2 +- yarn.lock | 50 +--------- 4 files changed, 59 insertions(+), 92 deletions(-) diff --git a/package.json b/package.json index 859f059..2ad9893 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "eslint-config-prettier": "^8.5.0", "fs-extra": "^11.1.0", "git-cz": "^4.9.0", - "got": "11.8.3", "husky": "^8.0.2", "mime-types": "^2.1.35", "only-allow": "^1.1.1", diff --git a/packages/docs/src/routes/docs/flows/index.mdx b/packages/docs/src/routes/docs/flows/index.mdx index 0cb1222..29a0c63 100644 --- a/packages/docs/src/routes/docs/flows/index.mdx +++ b/packages/docs/src/routes/docs/flows/index.mdx @@ -29,13 +29,16 @@ const flowPrincipal = addKeyword(['hola', 'alo']) Es importante que el número **vaya acompañado de su prefijo**, en el caso de España "34". ```js -createBot({ +createBot( + { flow: adapterFlow, provider: adapterProvider, database: adapterDB, - },{ - blackList:['34XXXXXXXXX','34XXXXXXXXX','34XXXXXXXXX','34XXXXXXXXX'] - }) + }, + { + blackList: ['34XXXXXXXXX', '34XXXXXXXXX', '34XXXXXXXXX', '34XXXXXXXXX'], + } +) ``` --- @@ -175,65 +178,74 @@ const flowString = addKeyword('hola') ``` --- + ## endFlow() -Esta funcion se utliza para finalizar un flujo con dos o más addAnswer. Un ejemplo de uso sería registrar 3 datos de un usuario en 3 preguntas distinas y +Esta funcion se utliza para finalizar un flujo con dos o más addAnswer. Un ejemplo de uso sería registrar 3 datos de un usuario en 3 preguntas distinas y que el usuario pueda finalizar por él mismo el flujo. Como podrás comprobar en el ejemplo siguiente, se puede vincular flowDynamic y todas sus funciones; como por ejemplo botones. - - ```js const flowFormulario = addKeyword(['Hola']) - -.addAnswer(['Hola!','Escriba su *Nombre* para generar su solicitud'], -{capture: true,buttons:[{body:'❌ Cancelar solicitud'}]}, -async (ctx,{flowDynamic, endFlow})=>{ - if(ctx.body == '❌ Cancelar solicitud'){ - await flowDynamic([{body: "❌ *Su solicitud de cita ha sido cancelada* ❌", buttons:[{body:'⬅️ Volver al Inicio'}]}]) - return endFlow() - } - }) - .addAnswer(['También necesito tus dos apellidos'], - {capture: true,buttons:[{body:'❌ Cancelar solicitud'}]}, - async (ctx,{flowDynamic, endFlow})=>{ - if(ctx.body == '❌ Cancelar solicitud'){ - await flowDynamic([{body: "❌ *Su solicitud de cita ha sido cancelada* ❌", buttons:[{body:'⬅️ Volver al Inicio'}]}]) - return endFlow() - } - }) - .addAnswer(['Dejeme su número de teléfono y le llamaré lo antes posible.'], -{capture: true,buttons:[{body:'❌ Cancelar solicitud'}]}, -async (ctx,{flowDynamic, endFlow})=>{ - if(ctx.body == '❌ Cancelar solicitud'){ - await flowDynamic([{body: "❌ *Su solicitud de cita ha sido cancelada* ❌", buttons:[{body:'⬅️ Volver al Inicio'}]}]) - return endFlow() - } - }) - - - + .addAnswer( + ['Hola!', 'Escriba su *Nombre* para generar su solicitud'], + { capture: true, buttons: [{ body: '❌ Cancelar solicitud' }] }, + async (ctx, { flowDynamic, endFlow }) => { + if (ctx.body == '❌ Cancelar solicitud') { + await flowDynamic([ + { + body: '❌ *Su solicitud de cita ha sido cancelada* ❌', + buttons: [{ body: '⬅️ Volver al Inicio' }], + }, + ]) + return endFlow() + } + } + ) + .addAnswer( + ['También necesito tus dos apellidos'], + { capture: true, buttons: [{ body: '❌ Cancelar solicitud' }] }, + async (ctx, { flowDynamic, endFlow }) => { + if (ctx.body == '❌ Cancelar solicitud') { + await flowDynamic([ + { + body: '❌ *Su solicitud de cita ha sido cancelada* ❌', + buttons: [{ body: '⬅️ Volver al Inicio' }], + }, + ]) + return endFlow() + } + } + ) + .addAnswer( + ['Dejeme su número de teléfono y le llamaré lo antes posible.'], + { capture: true, buttons: [{ body: '❌ Cancelar solicitud' }] }, + async (ctx, { flowDynamic, endFlow }) => { + if (ctx.body == '❌ Cancelar solicitud') { + await flowDynamic([ + { + body: '❌ *Su solicitud de cita ha sido cancelada* ❌', + buttons: [{ body: '⬅️ Volver al Inicio' }], + }, + ]) + return endFlow() + } + } + ) ``` --- - - - - # QRPortalWeb Argumento para asignar nombre y puerto al BOT ```js -QRPortalWeb({name:BOTNAME, port:3005 }); - +QRPortalWeb({ name: BOTNAME, port: 3005 }) ``` --- - -