From 8cbfd560a3585750c6edbccd544a21318c71c337 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Mon, 16 Jan 2023 09:13:52 +0100 Subject: [PATCH 01/27] =?UTF-8?q?ci(providers):=20=EF=BF=BD=20Check=20BREA?= =?UTF-8?q?KING=20CHANGE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/provider/src/web-whatsapp/package.json | 2 +- starters/apps/base-wweb-json/package.json | 2 +- starters/apps/base-wweb-memory/package.json | 2 +- starters/apps/base-wweb-mongo/package.json | 2 +- starters/apps/base-wweb-mysql/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/provider/src/web-whatsapp/package.json b/packages/provider/src/web-whatsapp/package.json index 7514818..d15dbe0 100644 --- a/packages/provider/src/web-whatsapp/package.json +++ b/packages/provider/src/web-whatsapp/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "whatsapp-web.js": "1.18.4" + "whatsapp-web.js": "1.19.2" } } diff --git a/starters/apps/base-wweb-json/package.json b/starters/apps/base-wweb-json/package.json index f52ab5a..d01b825 100644 --- a/starters/apps/base-wweb-json/package.json +++ b/starters/apps/base-wweb-json/package.json @@ -14,7 +14,7 @@ "@bot-whatsapp/database": "latest", "@bot-whatsapp/provider": "latest", "@bot-whatsapp/portal": "latest", - "whatsapp-web.js": "1.18.4" + "whatsapp-web.js": "1.19.2" }, "author": "", "license": "ISC" diff --git a/starters/apps/base-wweb-memory/package.json b/starters/apps/base-wweb-memory/package.json index b9c4712..d508c4f 100644 --- a/starters/apps/base-wweb-memory/package.json +++ b/starters/apps/base-wweb-memory/package.json @@ -14,7 +14,7 @@ "@bot-whatsapp/database": "latest", "@bot-whatsapp/provider": "latest", "@bot-whatsapp/portal": "latest", - "whatsapp-web.js": "1.18.4" + "whatsapp-web.js": "1.19.2" }, "author": "", "license": "ISC" diff --git a/starters/apps/base-wweb-mongo/package.json b/starters/apps/base-wweb-mongo/package.json index 9c51d8a..a64f35c 100644 --- a/starters/apps/base-wweb-mongo/package.json +++ b/starters/apps/base-wweb-mongo/package.json @@ -9,7 +9,7 @@ }, "keywords": [], "dependencies": { - "whatsapp-web.js": "1.18.4", + "whatsapp-web.js": "1.19.2", "@bot-whatsapp/bot": "latest", "@bot-whatsapp/cli": "latest", "@bot-whatsapp/database": "latest", diff --git a/starters/apps/base-wweb-mysql/package.json b/starters/apps/base-wweb-mysql/package.json index e95ec1a..ee90e12 100644 --- a/starters/apps/base-wweb-mysql/package.json +++ b/starters/apps/base-wweb-mysql/package.json @@ -9,7 +9,7 @@ }, "keywords": [], "dependencies": { - "whatsapp-web.js": "1.18.4", + "whatsapp-web.js": "1.19.2", "@bot-whatsapp/bot": "latest", "@bot-whatsapp/cli": "latest", "@bot-whatsapp/database": "latest", From 5174c6b3bb5139735c57d1d8554afd961d39acaa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 09:10:45 +0000 Subject: [PATCH 02/27] docs(contributor): contrib-readme-action has updated readme --- README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b4a2271..777209f 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,13 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación. + + + + - + + + + + - + + + - + + + +
+ + cheveguerra +
+ Jose Alberto Guerra Ugalde +
+
leifermendez @@ -62,6 +69,21 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación. Leifer Mendez + + danielcasta0398 +
+ Juan Daniel Castaño +
+
+ + marianarolfo +
+ Null +
+
HKong31 @@ -75,8 +97,14 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
Zvi
-
+ + JosephVTX +
+ Joseph Vega Callupe +
+
Gonzalito87 @@ -84,6 +112,21 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación. Null + + jlferrete +
+ Jose Luis Ferrete Olarte +
+
+ + 6rak0 +
+ Null +
+
tonyvazgar @@ -91,13 +134,6 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación. Luis Antonio Vázquez García - - ulisesvina -
- Ulises Viña -
-
rrruuuyyy From eab39e4ac06fd46f1a4671f8c15d1456b4400b97 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Tue, 24 Jan 2023 16:54:31 +0100 Subject: [PATCH 03/27] 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 04/27] 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 05/27] 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 b2feaea588278a4bf85cfaf70e4673d8f2bc7226 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Wed, 25 Jan 2023 09:05:01 +0100 Subject: [PATCH 06/27] docs: :bug: fix modal --- packages/docs/src/routes/docs/layout!.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/src/routes/docs/layout!.tsx b/packages/docs/src/routes/docs/layout!.tsx index 4d66df2..8f49e8a 100644 --- a/packages/docs/src/routes/docs/layout!.tsx +++ b/packages/docs/src/routes/docs/layout!.tsx @@ -3,7 +3,7 @@ import type { DocumentHead } from '@builder.io/qwik-city' import ExtraBar from '~/components/widgets/ExtraBar' import Header from '~/components/widgets/Header' import NavBar from '~/components/widgets/NavBar' -import { SearchModal } from '~/components/widgets/SearchModal' +// import { SearchModal } from '~/components/widgets/SearchModal' import SponsorBar from '~/components/widgets/SponsorBar' import { GlobalStore } from '~/contexts' // import Navigation from '~/components/widgets/Navigation' @@ -15,7 +15,7 @@ export default component$(() => { return ( <> - + {/* */}
From e7a8e85ead9a7dffbdbb04e172f83c3f66bc7262 Mon Sep 17 00:00:00 2001 From: lisandroprada Date: Wed, 25 Jan 2023 08:21:12 -0300 Subject: [PATCH 07/27] Update index.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agregado: Definición de la constante BOTNAME. --- packages/docs/src/routes/docs/flows/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docs/src/routes/docs/flows/index.mdx b/packages/docs/src/routes/docs/flows/index.mdx index 0cb1222..cf6c23c 100644 --- a/packages/docs/src/routes/docs/flows/index.mdx +++ b/packages/docs/src/routes/docs/flows/index.mdx @@ -226,6 +226,7 @@ async (ctx,{flowDynamic, endFlow})=>{ Argumento para asignar nombre y puerto al BOT ```js +const BOTNAME = 'bot'; QRPortalWeb({name:BOTNAME, port:3005 }); ``` 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 08/27] 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 09/27] 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 10/27] 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 11/27] 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 12/27] 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 13/27] 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 14/27] 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 e22780d3faba94f71a70f1f201a20690608fa5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leifer=20Jes=C3=BAs=20Mendez?= Date: Sat, 28 Jan 2023 15:46:13 +0100 Subject: [PATCH 15/27] fix(bot): :zap: fix fallback refactor --- __test__/05-case.test.js | 118 ++++++++++++++++++ packages/bot/core/core.class.js | 48 ++++--- packages/docs/src/routes/docs/flows/index.mdx | 98 ++++++++------- 3 files changed, 204 insertions(+), 60 deletions(-) create mode 100644 __test__/05-case.test.js diff --git a/__test__/05-case.test.js b/__test__/05-case.test.js new file mode 100644 index 0000000..6ca65d0 --- /dev/null +++ b/__test__/05-case.test.js @@ -0,0 +1,118 @@ +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) +} + +test(`[Caso - 05] Continuar Flujo (continueFlow)`, async () => { + const MOCK_VALUES = [ + '¿CUal es tu email?', + 'Continuamos....', + '¿Cual es tu edad?', + ] + const provider = createProvider(PROVIDER_DB) + const database = new MOCK_DB() + + const flujoPrincipal = addKeyword(['hola']) + .addAnswer( + MOCK_VALUES[0], + { + capture: true, + }, + async (ctx, { flowDynamic, fallBack }) => { + const validation = ctx.body.includes('@') + + if (validation) { + const getDataFromApi = await fakeHTTP([ + 'Gracias por tu email se ha validado de manera correcta', + ]) + return flowDynamic(getDataFromApi) + } + return fallBack(validation) + } + ) + .addAnswer(MOCK_VALUES[1]) + .addAnswer( + MOCK_VALUES[2], + { capture: true }, + async (ctx, { flowDynamic, fallBack }) => { + if (ctx.body !== '18') { + await delay(50) + return fallBack(false, 'Ups creo que no eres mayor de edad') + } + return flowDynamic('Bien tu edad es correcta!') + } + ) + .addAnswer('Puedes pasar') + + createBot({ + database, + flow: createFlow([flujoPrincipal]), + provider, + }) + + provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + provider.delaySendMessage(10, 'message', { + from: '000', + body: 'this is not email value', + }) + + provider.delaySendMessage(20, 'message', { + from: '000', + body: 'test@test.com', + }) + + provider.delaySendMessage(90, 'message', { + from: '000', + body: '20', + }) + + provider.delaySendMessage(200, 'message', { + from: '000', + body: '18', + }) + + await delay(1200) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is(MOCK_VALUES[0], getHistory[0]) + assert.is('this is not email value', getHistory[1]) + assert.is(MOCK_VALUES[0], getHistory[2]) + assert.is('test@test.com', getHistory[3]) + assert.is( + '1 Gracias por tu email se ha validado de manera correcta', + getHistory[4] + ) + assert.is(MOCK_VALUES[1], getHistory[5]) + assert.is(MOCK_VALUES[2], getHistory[6]) + assert.is('20', getHistory[7]) + assert.is('Ups creo que no eres mayor de edad', getHistory[8]) + assert.is('18', getHistory[9]) + assert.is('Bien tu edad es correcta!', getHistory[10]) + assert.is('Puedes pasar', getHistory[11]) +}) + +test.run() + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index f7051b3..418fef4 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -71,8 +71,8 @@ class CoreClass { logger.log(`[handleMsg]: `, messageCtxInComming) const { body, from } = messageCtxInComming let msgToSend = [] - let fallBackFlag = false let endFlowFlag = false + let fallBackFlag = false if (this.generalArgs.blackList.includes(from)) return if (!body) return if (!body.length) return @@ -105,11 +105,23 @@ class CoreClass { return } - // 📄 Esta funcion se encarga de enviar un array de mensajes dentro de este ctx - const sendFlow = async (messageToSend, numberOrId) => { - // [1 Paso] esto esta bien! + // 📄 Continuar con el siguiente flujo + const continueFlow = async () => { + const cotinueMessage = + this.flowClass.find(refToContinue?.ref, true) || [] + sendFlow(cotinueMessage, from, { continue: true }) + 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) - if (prevMsg?.options?.capture) await cbEveryCtx(prevMsg?.ref) const queue = [] for (const ctxMessage of messageToSend) { if (endFlowFlag) return @@ -127,11 +139,13 @@ class CoreClass { } // 📄 [options: fallBack]: esta funcion se encarga de repetir el ultimo mensaje - const fallBack = async () => { - fallBackFlag = true - await this.sendProviderAndSave(from, refToContinue) + const fallBack = async (next = false, message = null) => { QueuePrincipal.queue = [] - return refToContinue + if (next) return continueFlow() + return this.sendProviderAndSave(from, { + ...refToContinue, + answer: message ?? refToContinue.answer, + }) } // 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes @@ -141,8 +155,7 @@ class CoreClass { listMsg = [], optListMsg = { limit: 5, fallback: false } ) => { - if (!Array.isArray(listMsg)) - throw new Error('Esto debe ser un ARRAY') + if (!Array.isArray(listMsg)) listMsg = [listMsg] fallBackFlag = optListMsg.fallback const parseListMsg = listMsg @@ -165,7 +178,7 @@ class CoreClass { for (const msg of parseListMsg) { await this.sendProviderAndSave(from, msg) } - return + return continueFlow() } // 📄 Se encarga de revisar si el contexto del mensaje tiene callback o fallback @@ -181,11 +194,12 @@ class CoreClass { fallBack, flowDynamic, endFlow, + continueFlow, }) } // 📄🤘(tiene return) [options: nested(array)]: Si se tiene flujos hijos los implementa - if (!fallBackFlag && prevMsg?.options?.nested?.length) { + if (prevMsg?.options?.nested?.length) { const nestedRef = prevMsg.options.nested const flowStandalone = nestedRef.map((f) => ({ ...nestedRef.find((r) => r.refSerialize === f.refSerialize), @@ -197,12 +211,11 @@ class CoreClass { return } - // 📄🤘(tiene return) [options: capture (boolean)]: Si se tiene option boolean - if (!fallBackFlag && !prevMsg?.options?.nested?.length) { + // 📄🤘(tiene return) Si el mensaje previo implementa capture + if (!prevMsg?.options?.nested?.length) { const typeCapture = typeof prevMsg?.options?.capture - const valueCapture = prevMsg?.options?.capture - if (['string', 'boolean'].includes(typeCapture) && valueCapture) { + if (typeCapture === 'boolean' && fallBackFlag) { msgToSend = this.flowClass.find(refToContinue?.ref, true) || [] sendFlow(msgToSend, from) return @@ -228,6 +241,7 @@ class CoreClass { } /** + * @deprecated * @private * @param {*} message * @param {*} ref 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 }) ``` --- - - Date: Sat, 28 Jan 2023 16:06:12 +0100 Subject: [PATCH 16/27] fix(cli): :zap: refactor fallback in child flow --- packages/bot/core/core.class.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index 418fef4..b3bc15b 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -143,8 +143,8 @@ class CoreClass { QueuePrincipal.queue = [] if (next) return continueFlow() return this.sendProviderAndSave(from, { - ...refToContinue, - answer: message ?? refToContinue.answer, + ...prevMsg, + answer: message ?? prevMsg.answer, }) } From f95331d3dc70e76a3dfbe4c8d24059f0e7a164ef Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Sat, 28 Jan 2023 16:25:22 +0100 Subject: [PATCH 17/27] 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 }) ``` --- - - Date: Sat, 28 Jan 2023 16:44:30 +0100 Subject: [PATCH 18/27] feat(provider): :zap: venom wweb --- packages/bot/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bot/package.json b/packages/bot/package.json index fe542c1..30211e4 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.73-alpha.0", + "version": "0.0.84-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": { From 1c66f178a56d284bb8cb9df5ca17685c7e5d1ddd Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Sat, 28 Jan 2023 18:41:58 +0100 Subject: [PATCH 19/27] fix(cli): :zap: endflow --- __test__/06-case.test.js | 111 ++++++++++++++++++++++++++++++++ packages/bot/core/core.class.js | 11 +++- packages/bot/package.json | 2 +- 3 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 __test__/06-case.test.js diff --git a/__test__/06-case.test.js b/__test__/06-case.test.js new file mode 100644 index 0000000..c68679e --- /dev/null +++ b/__test__/06-case.test.js @@ -0,0 +1,111 @@ +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) +} + +test(`[Caso - 06] Finalizar Flujo (endFlow)`, async () => { + const MOCK_VALUES = [ + '¿CUal es tu email?', + 'Continuamos....', + '¿Cual es tu edad?', + ] + const provider = createProvider(PROVIDER_DB) + const database = new MOCK_DB() + + const flujoPrincipal = addKeyword(['hola']) + .addAnswer( + MOCK_VALUES[0], + { + capture: true, + }, + async (ctx, { flowDynamic, fallBack }) => { + const validation = ctx.body.includes('@') + + if (validation) { + const getDataFromApi = await fakeHTTP([ + 'Gracias por tu email se ha validado de manera correcta', + ]) + return flowDynamic(getDataFromApi) + } + return fallBack(validation) + } + ) + .addAnswer(MOCK_VALUES[1], null, async (_, { endFlow }) => { + return endFlow() + }) + .addAnswer( + MOCK_VALUES[2], + { capture: true }, + async (ctx, { flowDynamic, fallBack }) => { + if (ctx.body !== '18') { + await delay(50) + return fallBack(false, 'Ups creo que no eres mayor de edad') + } + return flowDynamic('Bien tu edad es correcta!') + } + ) + .addAnswer('Puedes pasar') + + createBot({ + database, + flow: createFlow([flujoPrincipal]), + provider, + }) + + provider.delaySendMessage(0, 'message', { + from: '000', + body: 'hola', + }) + + provider.delaySendMessage(10, 'message', { + from: '000', + body: 'this is not email value', + }) + + provider.delaySendMessage(20, 'message', { + from: '000', + body: 'test@test.com', + }) + + provider.delaySendMessage(90, 'message', { + from: '000', + body: '20', + }) + + await delay(1200) + const getHistory = database.listHistory.map((i) => i.answer) + assert.is(MOCK_VALUES[0], getHistory[0]) + assert.is('this is not email value', getHistory[1]) + assert.is(MOCK_VALUES[0], getHistory[2]) + assert.is('test@test.com', getHistory[3]) + assert.is( + '1 Gracias por tu email se ha validado de manera correcta', + getHistory[4] + ) + assert.is(MOCK_VALUES[1], getHistory[5]) + assert.is('20', getHistory[6]) + assert.is(undefined, getHistory[7]) +}) + +test.run() + +function delay(ms) { + return new Promise((res) => setTimeout(res, ms)) +} diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index b3bc15b..90340e6 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -98,10 +98,15 @@ class CoreClass { } // 📄 Finalizar flujo - const endFlow = async () => { + const endFlow = async (message = null) => { prevMsg = null endFlowFlag = true clearQueue() + if (message) + this.sendProviderAndSave(from, { + ...prevMsg, + answer: message ?? prevMsg.answer, + }) return } @@ -199,7 +204,7 @@ class CoreClass { } // 📄🤘(tiene return) [options: nested(array)]: Si se tiene flujos hijos los implementa - if (prevMsg?.options?.nested?.length) { + if (!endFlowFlag && prevMsg?.options?.nested?.length) { const nestedRef = prevMsg.options.nested const flowStandalone = nestedRef.map((f) => ({ ...nestedRef.find((r) => r.refSerialize === f.refSerialize), @@ -212,7 +217,7 @@ class CoreClass { } // 📄🤘(tiene return) Si el mensaje previo implementa capture - if (!prevMsg?.options?.nested?.length) { + if (!endFlowFlag && !prevMsg?.options?.nested?.length) { const typeCapture = typeof prevMsg?.options?.capture if (typeCapture === 'boolean' && fallBackFlag) { diff --git a/packages/bot/package.json b/packages/bot/package.json index 30211e4..827194b 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.84-alpha.0", + "version": "0.0.86-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": { From b655ae449e7958ea940d8cc3c678fd66f60b6385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leifer=20Jes=C3=BAs=20Mendez?= Date: Sun, 29 Jan 2023 12:46:31 +0100 Subject: [PATCH 20/27] fix(bot): :fire: endFlow with ctx --- packages/bot/core/core.class.js | 48 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index b3bc15b..9ddf444 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -91,6 +91,25 @@ class CoreClass { this.databaseClass.save(ctxByNumber) } + // 📄 Crar CTX de mensaje (uso private) + const createCtxMessage = (payload = {}, index = 0) => { + const body = + typeof payload === 'string' + ? payload + : payload?.body ?? payload?.answer + const media = payload?.media ?? null + const buttons = payload?.buttons ?? [] + const capture = payload?.capture ?? false + + return toCtx({ + body, + from, + keyword: null, + index, + options: { media, buttons, capture }, + }) + } + // 📄 Limpiar cola de procesos const clearQueue = () => { QueuePrincipal.pendingPromise = false @@ -98,9 +117,12 @@ class CoreClass { } // 📄 Finalizar flujo - const endFlow = async () => { + const endFlow = async (message = null) => { prevMsg = null endFlowFlag = true + if (message) + this.sendProviderAndSave(from, createCtxMessage(message)) + clearQueue() return } @@ -151,28 +173,12 @@ class CoreClass { // 📄 [options: flowDynamic]: esta funcion se encarga de responder un array de respuesta esta limitado a 5 mensajes // para evitar bloque de whatsapp - const flowDynamic = async ( - listMsg = [], - optListMsg = { limit: 5, fallback: false } - ) => { + const flowDynamic = async (listMsg = []) => { if (!Array.isArray(listMsg)) listMsg = [listMsg] - fallBackFlag = optListMsg.fallback - const parseListMsg = listMsg - .map((opt, index) => { - const body = typeof opt === 'string' ? opt : opt.body - const media = opt?.media ?? null - const buttons = opt?.buttons ?? [] - - return toCtx({ - body, - from, - keyword: null, - index, - options: { media, buttons }, - }) - }) - .slice(0, optListMsg.limit) + const parseListMsg = listMsg.map((opt, index) => + createCtxMessage(opt, index) + ) if (endFlowFlag) return for (const msg of parseListMsg) { From f6114affadfbc324536a86167d1fdfe8da3c8de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leifer=20Jes=C3=BAs=20Mendez?= Date: Sun, 29 Jan 2023 13:39:09 +0100 Subject: [PATCH 21/27] fix(bot): :fire: endFlow with ctx --- packages/bot/core/core.class.js | 9 ++++++++- packages/bot/package.json | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/bot/core/core.class.js b/packages/bot/core/core.class.js index 9ddf444..60644a5 100644 --- a/packages/bot/core/core.class.js +++ b/packages/bot/core/core.class.js @@ -166,7 +166,14 @@ class CoreClass { if (next) return continueFlow() return this.sendProviderAndSave(from, { ...prevMsg, - answer: message ?? prevMsg.answer, + answer: + typeof message === 'string' + ? message + : message?.body ?? prevMsg.answer, + options: { + ...prevMsg.options, + buttons: message?.buttons ?? prevMsg.options?.buttons, + }, }) } diff --git a/packages/bot/package.json b/packages/bot/package.json index 30211e4..5d2dc0c 100644 --- a/packages/bot/package.json +++ b/packages/bot/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/bot", - "version": "0.0.84-alpha.0", + "version": "0.0.89-alpha.0", "description": "", "main": "./lib/bundle.bot.cjs", "scripts": { From f7d90efc2f48dad8fed3cbd21b2578ad296c2bd6 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Sun, 29 Jan 2023 18:33:32 +0100 Subject: [PATCH 22/27] chore(release): 0.1.19 --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b39939..d0bdbfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,36 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.1.19](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.18...v0.1.19) (2023-01-29) + + +### Features + +* :fire: bailey add media ([eab39e4](https://github.com/leifermendez/bot-whatsapp/commit/eab39e4ac06fd46f1a4671f8c15d1456b4400b97)) +* :zap: more feature ([e19c3a2](https://github.com/leifermendez/bot-whatsapp/commit/e19c3a25a40259c74b4add9635af4844907eed26)) +* **provider:** :rocket: fix issues in providers venom and wwebjs ([cbe438b](https://github.com/leifermendez/bot-whatsapp/commit/cbe438b77854e8df48b9dafaf7a837d21124ac5f)) +* **provider:** :rocket: fix provider ([0ad4c58](https://github.com/leifermendez/bot-whatsapp/commit/0ad4c58457b548dc41c0f9e8470d59c48de7b95a)) +* **provider:** :rocket: fix provider ([f8c7184](https://github.com/leifermendez/bot-whatsapp/commit/f8c7184487065443ab10f77aaf585e8bd63ca441)) +* **provider:** :rocket: fix provider ([b2afa45](https://github.com/leifermendez/bot-whatsapp/commit/b2afa45352a7ab1f5d9775f3c1fde475bd8ca204)) +* **provider:** :rocket: fix provider venom and wwebjs ([dcb0566](https://github.com/leifermendez/bot-whatsapp/commit/dcb0566d2bc3da40cd0c71554bb5ea0ec115d9ca)) +* **provider:** :rocket: implements all send media to venom provider ([9dd7c02](https://github.com/leifermendez/bot-whatsapp/commit/9dd7c02b6a5474aff063f7d6be0ca8519504b93c)) +* **provider:** :rocket: send file wwebjs ([6ff1a3a](https://github.com/leifermendez/bot-whatsapp/commit/6ff1a3a980196c01c66ed04ee07d0e7e57256504)) +* **provider:** :zap: bailey add send file video audio ([14d1a61](https://github.com/leifermendez/bot-whatsapp/commit/14d1a61fa259c09135c37c55bd79e97c9c8367e4)) +* **provider:** :zap: venom wweb ([fd2847a](https://github.com/leifermendez/bot-whatsapp/commit/fd2847aea0db17a0bdf33b5bca67a4cb8db2da16)) +* **provider:** :zap: venom wweb ([f95331d](https://github.com/leifermendez/bot-whatsapp/commit/f95331d3dc70e76a3dfbe4c8d24059f0e7a164ef)) +* **provider:** 🚀 implements all send media to venom provider ([bd7d150](https://github.com/leifermendez/bot-whatsapp/commit/bd7d150c047af41fdbb47f0a50a21e82cd79ee85)) + + +### Bug Fixes + +* **bot:** :fire: endFlow with ctx ([f6114af](https://github.com/leifermendez/bot-whatsapp/commit/f6114affadfbc324536a86167d1fdfe8da3c8de6)) +* **bot:** :fire: endFlow with ctx ([b655ae4](https://github.com/leifermendez/bot-whatsapp/commit/b655ae449e7958ea940d8cc3c678fd66f60b6385)) +* **bot:** :zap: endFlow butons ([87a4203](https://github.com/leifermendez/bot-whatsapp/commit/87a4203cd5b88f566387a76d586248e4265d6e4e)) +* **bot:** :zap: fix fallback refactor ([e22780d](https://github.com/leifermendez/bot-whatsapp/commit/e22780d3faba94f71a70f1f201a20690608fa5bf)) +* **cli:** :zap: endflow ([1c66f17](https://github.com/leifermendez/bot-whatsapp/commit/1c66f178a56d284bb8cb9df5ca17685c7e5d1ddd)) +* **cli:** :zap: refactor fallback in child flow ([b33e346](https://github.com/leifermendez/bot-whatsapp/commit/b33e34692d3abcb6874308a9be79f74be4a2c3a8)) +* **cli:** :zap: refactor fallback in child flow ([8da4b20](https://github.com/leifermendez/bot-whatsapp/commit/8da4b204b41125b5d0fa0aee4fa87c1f5faf5568)) + ### [0.1.18](https://github.com/leifermendez/bot-whatsapp/compare/v0.1.17...v0.1.18) (2023-01-24) diff --git a/package.json b/package.json index 2ad9893..30e3cf4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bot-whatsapp/root", - "version": "0.1.18", + "version": "0.1.19", "description": "Bot de wahtsapp open source para MVP o pequeños negocios", "main": "app.js", "private": true, From 0a69b8d9b5180d40c373a9234eebdee966f6c4fb Mon Sep 17 00:00:00 2001 From: Jhonarias13 Date: Tue, 31 Jan 2023 09:35:02 -0500 Subject: [PATCH 23/27] corrige caption 'soy una imagen' en sendImage() wwebprovider --- packages/provider/src/web-whatsapp/index.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index 693d1b9..60a142d 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -163,13 +163,11 @@ class WebWhatsappProvider extends ProviderClass { * @param {*} text * @returns */ - sendImage = async (number, filePath) => { + sendImage = async (number, filePath, caption) => { 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', - }) + return this.vendor.sendMessage(number, media, { caption }) } /** @@ -180,13 +178,11 @@ class WebWhatsappProvider extends ProviderClass { * @returns */ - sendAudio = async (number, filePath) => { + sendAudio = async (number, filePath, caption) => { 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', - }) + return this.vendor.sendMessage(number, media, { caption }) } /** @@ -235,7 +231,7 @@ class WebWhatsappProvider extends ProviderClass { if (mimeType.includes('video')) return this.sendVideo(number, fileDownloaded) if (mimeType.includes('audio')) - return this.sendAudio(number, fileDownloaded) + return this.sendAudio(number, fileDownloaded, text) return this.sendFile(number, fileDownloaded) } From 331d2a309c3377342c8e7d9519c19e9456a4f78c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 09:10:57 +0000 Subject: [PATCH 24/27] docs(contributor): contrib-readme-action has updated readme --- README.md | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 777209f..ce15a85 100644 --- a/README.md +++ b/README.md @@ -112,14 +112,35 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación. Null
+ + devrlbusiness +
+ Developer RL Business +
+
+ + Gregoriotecnico +
+ Null +
+
jlferrete
Jose Luis Ferrete Olarte
-
+ + lisandroprada +
+ Null +
+
6rak0 @@ -140,7 +161,8 @@ Entiende más a fondo sus funcionalidades explicadas en nuestra documentación.
Rodrigo Mendoza Cabrera
-
yond1994 From 811618b256975220dae402a9a69020d9f788e122 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Fri, 3 Feb 2023 10:12:45 +0100 Subject: [PATCH 25/27] docs: :sparkles: digitalocean sponsor --- .../docs/src/assets/images/digital-ocean.png | Bin 0 -> 9212 bytes .../src/components/atoms/DigitalOcean.tsx | 213 ++++++++++++++++++ .../src/components/widgets/SponsorBar.tsx | 17 +- 3 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 packages/docs/src/assets/images/digital-ocean.png create mode 100644 packages/docs/src/components/atoms/DigitalOcean.tsx diff --git a/packages/docs/src/assets/images/digital-ocean.png b/packages/docs/src/assets/images/digital-ocean.png new file mode 100644 index 0000000000000000000000000000000000000000..0d0163b02358556eca5f264990a0c67f534289b7 GIT binary patch literal 9212 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 ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/packages/docs/src/components/widgets/SponsorBar.tsx b/packages/docs/src/components/widgets/SponsorBar.tsx index c0d8183..f355691 100644 --- a/packages/docs/src/components/widgets/SponsorBar.tsx +++ b/packages/docs/src/components/widgets/SponsorBar.tsx @@ -7,6 +7,8 @@ import { src as qwik } from '~/assets/images/qwik.png?width=100&metadata' import { src as leanga } from '~/assets/images/leanga.png?width=40&metadata' // @ts-ignore import { src as netlify } from '~/assets/images/full-logo-light.png?width=100&metadata' +// @ts-ignore +import { src as digitalOcean } from '~/assets/images/digital-ocean.png?width=100&metadata' /** * options = [] array con la lista de opciones de la documentacion @@ -41,7 +43,20 @@ export default component$(() => { Qwind Hero Image (Cool dog) + + + +
  • + + + DigitalOcean From 88c05c12a4b79368307bc8733c7b95dc7bf3a9e8 Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Fri, 3 Feb 2023 10:24:48 +0100 Subject: [PATCH 26/27] docs: :sparkles: digitalocean sponsor --- .prettierrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc.json b/.prettierrc.json index e74ed9f..f0db82f 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -2,5 +2,6 @@ "trailingComma": "es5", "tabWidth": 4, "semi": false, - "singleQuote": true + "singleQuote": true, + "printWidth": 120 } From 74fb3b864d25a3cd4bafffe95f5122b504a6443e Mon Sep 17 00:00:00 2001 From: Leifer Mendez Date: Fri, 3 Feb 2023 10:39:17 +0100 Subject: [PATCH 27/27] docs: :sparkles: digitalocean sponsor --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ce15a85..af4b124 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # Chatbot Library ![](https://img.shields.io/npm/v/@bot-whatsapp/bot?color=%2300c200&label=%40bot-whatsapp) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) -[![BotWhatsapp Releases(Prod)](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml/badge.svg)](https://github.com/codigoencasa/bot-whatsapp/actions/workflows/releases.yml) - +[![](https://img.shields.io/discord/915193197645402142?logo=discord)](https://link.codigoencasa.com/DISCORD)