From 80ce234bf684ed94d436d8460f20dfb1a5507d07 Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Tue, 7 Jun 2022 17:27:03 -0300 Subject: [PATCH] new(whatsapp.gblib): New provider. --- packages/core.gbapp/services/GBCoreService.ts | 3 +- packages/core.gbapp/services/GBMinService.ts | 76 +++++--- .../services/WhatsappDirectLine.ts | 178 +++++++++++++----- 3 files changed, 181 insertions(+), 76 deletions(-) diff --git a/packages/core.gbapp/services/GBCoreService.ts b/packages/core.gbapp/services/GBCoreService.ts index 5b88ec4d..7caeeacd 100644 --- a/packages/core.gbapp/services/GBCoreService.ts +++ b/packages/core.gbapp/services/GBCoreService.ts @@ -301,8 +301,7 @@ ENDPOINT_UPDATE=true try { if (fs.existsSync('node_modules/ngrok/bin/ngrok.exe') || fs.existsSync('node_modules/ngrok/bin/ngrok')) { const ngrok = require('ngrok'); - - return await ngrok.connect({ port: port }, 10); + return await ngrok.connect({ port: port }, 10); } else { GBLog.warn('ngrok executable not found (only tested on Windows). Check installation or node_modules folder.'); diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 182b5cb6..e7fe880e 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -325,17 +325,33 @@ export class GBMinService { private async WhatsAppCallback(req, res) { try { + if (req.body && req.body.webhook) { + res.status(200); + res.end(); + + return; + } + + let chatapi = false; // Detects if the message is echo from itself. - const id = req.body.messages[0].author.split('@')[0]; - const senderName = req.body.messages[0].senderName; + const id = chatapi ? req.body.messages[0].author.split('@')[0] : req.body.receiver; + const senderName = chatapi ? req.body.messages[0].senderName : req.body.user.name; const sec = new SecService(); let user = await sec.getUserFromSystemId(id); - if (req.body.messages[0].fromMe) { - res.end(); + if (chatapi) { + if (req.body.messages[0].fromMe) { + res.end(); - return; // Exit here. + return; // Exit here. + } + } else { + if (req.body.message.fromMe) { + res.end(); + + return; // Exit here. + } } let activeMin; @@ -349,23 +365,25 @@ export class GBMinService { // Processes group behaviour. - let text = req.body.messages[0].body; + let text = chatapi ? req.body.messages[0].body : req.body.message.text; text = text.replace(/\@\d+ /gi, ''); - // Ensures that the bot group is the active bot for the user (like switching). + if (chatapi) { + // Ensures that the bot group is the active bot for the user (like switching). - const message = req.body.messages[0]; - if (message.chatName.charAt(0) !== '+') { - const group = message.chatName; + const message = req.body.messages[0]; + if (message.chatName.charAt(0) !== '+') { + const group = message.chatName; - const botGroup = await this.core.loadInstanceByBotId(group); - if (user.instanceId !== botGroup.instanceId) { - await sec.updateUserInstance(id, botGroup.instanceId); + const botGroup = await this.core.loadInstanceByBotId(group); + if (user.instanceId !== botGroup.instanceId) { + await sec.updateUserInstance(id, botGroup.instanceId); + } + activeMin = GBServer.globals.minInstances.filter + (p => p.instance.instanceId === botGroup.instanceId)[0]; + await (activeMin as any).whatsAppDirectLine.received(req, res); + return; // EXIT HERE. } - activeMin = GBServer.globals.minInstances.filter - (p => p.instance.instanceId === botGroup.instanceId)[0]; - await (activeMin as any).whatsAppDirectLine.received(req, res); - return; // EXIT HERE. } @@ -400,7 +418,12 @@ export class GBMinService { if (startDialog) { GBLog.info(`Calling /start to Auto start ${startDialog} for ${activeMin.instance.instanceId}...`); - req.body.messages[0].body = `/start`; + if (chatapi) { + req.body.messages[0].body = `/start`; + } + else { + req.body.message = `/start`; + } // Resets HEAR ON DIALOG value to none and passes // current dialog to the direct line. @@ -431,7 +454,14 @@ export class GBMinService { if (startDialog) { GBLog.info(`Calling /start for Auto start : ${startDialog} for ${activeMin.instance.botId}...`); - req.body.messages[0].body = `/start`; + if (chatapi) { + req.body.messages[0].body = `/start`; + } + else { + req.body.message = `/start`; + } + + await (activeMin as any).whatsAppDirectLine.received(req, res); } else { await (activeMin as any).whatsAppDirectLine.sendToDevice( @@ -450,7 +480,7 @@ export class GBMinService { await (activeMin as any).whatsAppDirectLine.sendToDevice( id, `O outro Bot que você estava falando(${user.instanceId}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...` - ); + ); } await (activeMin as any).whatsAppDirectLine.received(req, res); } @@ -738,8 +768,8 @@ export class GBMinService { } }); - - + + if (min.instance.googlePrivateKey) { min['googleDirectLine'] = new GoogleChatDirectLine( min, @@ -789,7 +819,7 @@ export class GBMinService { min.dialogs = new DialogSet(dialogState); min.dialogs.add(new TextPrompt('textPrompt')); min.dialogs.add(new AttachmentPrompt('attachmentPrompt')); - + min.dialogs.add(new ConfirmPrompt('confirmPrompt')); if (process.env.ENABLE_AUTH) { min.dialogs.add( diff --git a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts index 74b28584..83869e62 100644 --- a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts +++ b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts @@ -66,6 +66,8 @@ export class WhatsappDirectLine extends GBService { public min: GBMinInstance; private directLineSecret: string; private locale: string = 'pt-BR'; + chatapi: any; + INSTANCE_URL = 'https://api.maytapi.com/api'; constructor( min: GBMinInstance, @@ -105,21 +107,43 @@ export class WhatsappDirectLine extends GBService { 'AuthorizationBotConnector', new Swagger.ApiKeyAuthorization('Authorization', `Bearer ${this.directLineSecret}`, 'header') ); + let options; - const options = { - method: 'POST', - url: urlJoin(this.whatsappServiceUrl, 'webhook'), - timeout: 10000, - qs: { - token: this.whatsappServiceKey, - webhookUrl: `${GBServer.globals.publicAddress}/webhooks/whatsapp/${this.botId}`, - set: true - }, - headers: { - 'cache-control': 'no-cache' - } - }; + if (this.chatapi) { + options = { + method: 'POST', + url: urlJoin(this.whatsappServiceUrl, 'webhook'), + timeout: 10000, + qs: { + token: this.whatsappServiceKey, + webhookUrl: `${GBServer.globals.publicAddress}/webhooks/whatsapp/${this.botId}`, + set: true + }, + headers: { + 'cache-control': 'no-cache' + } + }; + } + else { + + let phoneId = this.whatsappServiceNumber.split(';')[0]; + let productId = this.whatsappServiceNumber.split(';')[1] + + let url = `${this.INSTANCE_URL}/${productId}/setWebhook`; + let webhook = `${GBServer.globals.publicAddress}/webhooks/whatsapp/${this.botId}`; + + options = { + url: url, + method: 'POST', + body: { webhook: webhook, }, + headers: { + 'x-maytapi-key': this.whatsappServiceKey, + 'Content-Type': 'application/json', + }, + json: true, + }; + } if (setUrl) { const express = require('express'); GBServer.globals.server.use(`/audios`, express.static('work')); @@ -127,7 +151,6 @@ export class WhatsappDirectLine extends GBService { if (process.env.ENDPOINT_UPDATE === 'true') { try { const res = await request.post(options); - GBLog.info(res); } catch (error) { GBLog.error(`Error initializing 3rd party Whatsapp provider(1) ${error.message}`); } @@ -158,13 +181,13 @@ export class WhatsappDirectLine extends GBService { } public async received(req, res) { - if (req.body.messages === undefined) { + if (this.chatapi && req.body.messages === undefined) { res.end(); return; // Exit here. } - const message = req.body.messages[0]; + const message = this.chatapi ? req.body.messages[0] : req.body.message; let group = ""; const to = req.body.to; let answerText = null; @@ -242,7 +265,7 @@ export class WhatsappDirectLine extends GBService { } } - + await CollectionUtil.asyncForEach(this.min.appPackages, async (e: IGBPackage) => { await e.onExchangeData(this.min, 'whatsappMessage', message); @@ -370,7 +393,7 @@ export class WhatsappDirectLine extends GBService { WhatsappDirectLine.mobiles[generatedConversationId] = from; WhatsappDirectLine.usernames[from] = fromName; WhatsappDirectLine.chatIds[generatedConversationId] = message.chatId; - + this.pollMessages(client, generatedConversationId, from, fromName); this.inputMessage(client, generatedConversationId, text, from, fromName, group); @@ -487,21 +510,52 @@ export class WhatsappDirectLine extends GBService { } public async sendFileToDevice(to, url, filename, caption, chatId) { - const options = { - method: 'POST', - url: urlJoin(this.whatsappServiceUrl, 'sendFile'), - qs: { - token: this.whatsappServiceKey, - phone: chatId ? null : to, - chatId: chatId, - body: url, - filename: filename, - caption: caption - }, - headers: { - 'cache-control': 'no-cache' - } - }; + + let options; + if (this.chatapi) { + + options = { + method: 'POST', + url: urlJoin(this.whatsappServiceUrl, 'sendFile'), + qs: { + token: this.whatsappServiceKey, + phone: chatId ? null : to, + chatId: chatId, + body: url, + filename: filename, + caption: caption + }, + headers: { + 'cache-control': 'no-cache' + } + }; + + } + else { + // TODO: Attach. + let contents = 0; + let body = { + type: 'image', + text: 'Base64 Image Response', + message: `data:image/jpeg;base64,${contents}`, + }; + + let phoneId = this.whatsappServiceNumber.split(';')[0]; + let productId = this.whatsappServiceNumber.split(';')[1] + + + let url = `${this.INSTANCE_URL}/${productId}/${phoneId}/sendMessage`; + options = { + method: 'post', + json: true, + body, + headers: { + 'Content-Type': 'application/json', + 'x-maytapi-key': this.whatsappServiceKey, + }, + }; + + } try { // tslint:disable-next-line: await-promise @@ -538,10 +592,10 @@ export class WhatsappDirectLine extends GBService { public async sendTextAsAudioToDevice(to, msg, chatId) { - const url = await GBConversationalService.getAudioBufferFromText( - msg - ); - + const url = await GBConversationalService.getAudioBufferFromText( + msg + ); + await this.sendFileToDevice(to, url, 'Audio', msg, chatId); } @@ -557,21 +611,43 @@ export class WhatsappDirectLine extends GBService { return await this.sendTextAsAudioToDevice(to, msg, chatId); } else { - + let options; + if (this.chatapi) { + + options = { + method: 'POST', + url: urlJoin(this.whatsappServiceUrl, 'message'), + qs: { + token: this.whatsappServiceKey, + phone: chatId ? null : to, + chatId: chatId, + body: msg + }, + headers: { + 'cache-control': 'no-cache' + } + }; + } + else { + + let phoneId = this.whatsappServiceNumber.split(';')[0]; + let productId = this.whatsappServiceNumber.split(';')[1] + + + let url = `${this.INSTANCE_URL}/${productId}/${phoneId}/sendMessage`; + + + options = { + method: 'post', + json: true, + body: msg, + headers: { + 'Content-Type': 'application/json', + 'x-maytapi-key': this.whatsappServiceKey, + }, + }; + } - const options = { - method: 'POST', - url: urlJoin(this.whatsappServiceUrl, 'message'), - qs: { - token: this.whatsappServiceKey, - phone: chatId ? null : to, - chatId: chatId, - body: msg - }, - headers: { - 'cache-control': 'no-cache' - } - }; try { // tslint:disable-next-line: await-promise