diff --git a/packages/provider/src/twilio/index.js b/packages/provider/src/twilio/index.js index 973cc48..592e4d7 100644 --- a/packages/provider/src/twilio/index.js +++ b/packages/provider/src/twilio/index.js @@ -5,6 +5,12 @@ const TwilioWebHookServer = require('./server') const { parseNumber } = require('./utils') /** + * ⚙️TwilioProvider: Es un provedor que te ofrece enviar + * mensaje a Whatsapp via API + * info: https://www.twilio.com/es-mx/messaging/whatsapp + * video: https://youtu.be/KoOmsHylxUw + * + * Necesitas las siguientes tokens y valores * { accountSid, authToken, vendorNumber } */ class TwilioProvider extends ProviderClass { @@ -15,7 +21,7 @@ class TwilioProvider extends ProviderClass { super() this.vendor = new twilio(accountSid, authToken) this.twilioHook = new TwilioWebHookServer(_port) - this.vendorNumber = vendorNumber + this.vendorNumber = parseNumber(vendorNumber) this.twilioHook.start() const listEvents = this.busEvents() @@ -25,14 +31,6 @@ class TwilioProvider extends ProviderClass { } } - sendMessage = async (number, message) => { - return this.vendor.messages.create({ - body: message, - from: ['whatsapp:+', parseNumber(this.vendorNumber)].join(''), - to: ['whatsapp:+', parseNumber(number)].join(''), - }) - } - /** * Mapeamos los eventos nativos de whatsapp-web.js a los que la clase Provider espera * para tener un standar de eventos @@ -54,6 +52,65 @@ class TwilioProvider extends ProviderClass { }, }, ] + + /** + * Enviar un archivo multimedia + * https://www.twilio.com/es-mx/docs/whatsapp/tutorial/send-and-receive-media-messages-whatsapp-nodejs + * @private + * @param {*} number + * @param {*} mediaInput + * @returns + */ + sendMedia = async (number, message, mediaInput = null) => { + if (!mediaInput) throw new Error(`MEDIA_INPUT_NULL_: ${mediaInput}`) + number = parseNumber(number) + return this.vendor.messages.create({ + mediaUrl: [`${mediaInput}`], + body: message, + from: `whatsapp:+${this.vendorNumber}`, + to: `whatsapp:+${number}`, + }) + } + + /** + * Enviar botones + * https://www.twilio.com/es-mx/docs/whatsapp/buttons + * @private + * @param {*} number + * @param {*} message + * @param {*} buttons [] + * @returns + */ + sendButtons = async (number, message, buttons = []) => { + console.log(``) + console.log( + `[NOTA]: Actualmente enviar botons con Twilio esta en desarrollo` + ) + console.log( + `[NOTA]: https://www.twilio.com/es-mx/docs/whatsapp/buttons` + ) + console.log(``) + } + + /** + * + * @param {*} userId + * @param {*} message + * @param {*} param2 + * @returns + */ + sendMessage = async (number, message, { options }) => { + number = parseNumber(number) + if (options?.buttons?.length) + this.sendButtons(number, message, options.buttons) + if (options?.media) + return this.sendMedia(number, message, options.media) + return this.vendor.messages.create({ + body: message, + from: `whatsapp:+${this.vendorNumber}`, + to: `whatsapp:+${number}`, + }) + } } module.exports = TwilioProvider diff --git a/packages/provider/src/twilio/server.js b/packages/provider/src/twilio/server.js index d208232..ae09da7 100644 --- a/packages/provider/src/twilio/server.js +++ b/packages/provider/src/twilio/server.js @@ -11,6 +11,7 @@ class TwilioWebHookServer extends EventEmitter { twilioServer twilioPort constructor(_twilioPort) { + super() this.twilioServer = this.buildHTTPServer() this.twilioPort = _twilioPort } @@ -51,7 +52,7 @@ class TwilioWebHookServer extends EventEmitter { console.log(``) console.log(`[Twilio]: Agregar esta url "WHEN A MESSAGE COMES IN"`) console.log( - `[Twilio]: http://localhost:${this.twilioPort}/twilio-hook` + `[Twilio]: POST http://localhost:${this.twilioPort}/twilio-hook` ) console.log(`[Twilio]: Más información en la documentacion`) console.log(``) diff --git a/packages/provider/src/web-whatsapp/index.js b/packages/provider/src/web-whatsapp/index.js index 463987c..e3cafcf 100644 --- a/packages/provider/src/web-whatsapp/index.js +++ b/packages/provider/src/web-whatsapp/index.js @@ -8,14 +8,19 @@ const { const { ProviderClass } = require('@bot-whatsapp/bot') const { Console } = require('console') const { createWriteStream, existsSync } = require('fs') -const { cleanNumber, generateImage, isValidNumber } = require('./utils') +const { + cleanNumber, + generateImage, + isValidNumber, + downloadMedia, +} = require('./utils') const logger = new Console({ stdout: createWriteStream('./log'), }) /** - * WebWhatsappProvider: Es una clase tipo adaptor + * ⚙️ WebWhatsappProvider: Es una clase tipo adaptor * que extiende clases de ProviderClass (la cual es como interfaz para sber que funciones rqueridas) * https://github.com/pedroslopez/whatsapp-web.js */ @@ -97,9 +102,9 @@ class WebWhatsappProvider extends ProviderClass { * @returns */ sendMedia = async (number, mediaInput = null) => { - if (!existsSync(mediaInput)) - throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`) - const media = MessageMedia.fromFilePath(mediaInput) + if (!mediaInput) throw new Error(`NO_SE_ENCONTRO: ${mediaInput}`) + const fileDownloaded = await downloadMedia(mediaInput) + const media = MessageMedia.fromFilePath(fileDownloaded) return this.vendor.sendMessage(number, media, { sendAudioAsVoice: true, }) @@ -164,9 +169,9 @@ class WebWhatsappProvider extends ProviderClass { */ sendMessage = async (userId, message, { options }) => { const number = cleanNumber(userId) - if (options?.media) return this.sendMedia(number, options.media) if (options?.buttons?.length) return this.sendButtons(number, message, options.buttons) + if (options?.media) return this.sendMedia(number, options.media) return this.sendText(number, message) } } diff --git a/packages/provider/src/web-whatsapp/utils.js b/packages/provider/src/web-whatsapp/utils.js index aec861c..7981649 100644 --- a/packages/provider/src/web-whatsapp/utils.js +++ b/packages/provider/src/web-whatsapp/utils.js @@ -1,5 +1,8 @@ const { createWriteStream } = require('fs') const qr = require('qr-image') +const { tmpdir } = require('os') +const http = require('http') +const https = require('https') const cleanNumber = (number, full = false) => { number = number.replace('@c.us', '') @@ -18,4 +21,33 @@ const isValidNumber = (rawNumber) => { return !exist } -module.exports = { cleanNumber, generateImage, isValidNumber } +/** + * Incompleta + * Descargar archivo multimedia para enviar + * @param {*} url + * @returns + */ +const downloadMedia = (url) => { + return new Promise((resolve, reject) => { + const ext = url.split('.').pop() + const checkProtocol = url.includes('https:') + const handleHttp = checkProtocol ? https : http + const name = `tmp-${Date.now()}.${ext}` + const fullPath = `${tmpdir()}/${name}` + const file = createWriteStream(fullPath) + handleHttp.get(url, function (response) { + response.pipe(file) + file.on('finish', function () { + file.close() + resolve(fullPath) + }) + file.on('error', function () { + console.log('errro') + file.close() + reject(null) + }) + }) + }) +} + +module.exports = { cleanNumber, generateImage, isValidNumber, downloadMedia }