From 696e8673643ee43f1367ce09c8b41292489bc2a2 Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Tue, 21 Jun 2022 17:46:46 -0300 Subject: [PATCH] new(basic.gblib): Web Automation CAPTCHA processing. --- .../basic.gblib/services/DialogKeywords.ts | 556 +++++++++--------- packages/basic.gblib/services/GBVMService.ts | 6 +- packages/core.gbapp/services/GBMinService.ts | 6 +- .../services/WhatsappDirectLine.ts | 66 ++- 4 files changed, 316 insertions(+), 318 deletions(-) diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index bc154aa7..9bf2dee6 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -242,9 +242,9 @@ export class DialogKeywords { * @example TYPE page, "elementName", "text" */ public async type(step, page, idOrName, text) { - const e = await this.getBySelector(page, idOrName); - await e.type(text); -} + const e = await this.getBySelector(page, idOrName); + await e.type(text); + } /** * Returns the today data filled in dd/mm/yyyy or mm/dd/yyyy. @@ -252,48 +252,48 @@ export class DialogKeywords { * @example x = TODAY */ public async getOCR(step, localFile) { - const tesseract = require("node-tesseract-ocr") + const tesseract = require("node-tesseract-ocr") - const config = { - lang: "eng", - oem: 1, - psm: 3, + const config = { + lang: "eng", + oem: 1, + psm: 3, + } + + return await tesseract.recognize(localFile, config); } - return await tesseract.recognize(localFile, config); -} - /** * Returns the today data filled in dd/mm/yyyy or mm/dd/yyyy. * * @example x = TODAY */ public async getToday(step) { - let d = new Date(), - month = '' + (d.getMonth() + 1), - day = '' + d.getDate(), - year = d.getFullYear(); + let d = new Date(), + month = '' + (d.getMonth() + 1), + day = '' + d.getDate(), + year = d.getFullYear(); - if (month.length < 2) { month = '0' + month; } - if (day.length < 2) { day = '0' + day; } + if (month.length < 2) { month = '0' + month; } + if (day.length < 2) { day = '0' + day; } - const contentLocale = this.min.core.getParam( - this.min.instance, - 'Default Content Language', - GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') - ); + const contentLocale = this.min.core.getParam( + this.min.instance, + 'Default Content Language', + GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') + ); - switch (contentLocale) { - case 'pt': - return [day, month, year].join('/'); + switch (contentLocale) { + case 'pt': + return [day, month, year].join('/'); - case 'en': - return [month, day, year].join('/'); + case 'en': + return [month, day, year].join('/'); - default: - return [year, month, day].join('/'); + default: + return [year, month, day].join('/'); + } } -} /** * Quits the dialog, currently required to get out of VM context. @@ -301,11 +301,11 @@ export class DialogKeywords { * @example EXIT */ public async exit(step) { - if (this.browser) { - await this.browser.close(); + if (this.browser) { + await this.browser.close(); + } + await step.endDialog(); } - await step.endDialog(); -} /** * Get active tasks. @@ -313,9 +313,9 @@ export class DialogKeywords { * @example list = ACTIVE TASKS */ public async getActiveTasks() { - let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY); - return await s.getActiveTasks(); -} + let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY); + return await s.getActiveTasks(); + } /** * Creates a new deal. @@ -323,10 +323,10 @@ export class DialogKeywords { * @example CREATE DEAL dealname, contato, empresa, amount */ public async createDeal(dealName, contact, company, amount) { - let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY); - let deal = await s.createDeal(dealName, contact, company, amount); - return deal; -} + let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY); + let deal = await s.createDeal(dealName, contact, company, amount); + return deal; + } /** * Finds contacts in XRM. @@ -334,25 +334,25 @@ export class DialogKeywords { * @example list = FIND CONTACT "Sandra" */ public async fndContact(name) { - let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY); - return await s.searchContact(name); -} + let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY); + return await s.searchContact(name); + } public getContentLocaleWithCulture(contentLocale) { - switch (contentLocale) { - case 'pt': - return 'pt-BR'; + switch (contentLocale) { + case 'pt': + return 'pt-BR'; - case 'en': - return 'en-US'; + case 'en': + return 'en-US'; + + default: + return 'en-us'; + } - default: - return 'en-us'; } -} - /** * Returns specified date week day in format 'Mon'. * @@ -361,26 +361,26 @@ export class DialogKeywords { */ public getWeekFromDate(date) { - const contentLocale = this.min.core.getParam( - this.min.instance, - 'Default Content Language', - GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') - ); + const contentLocale = this.min.core.getParam( + this.min.instance, + 'Default Content Language', + GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') + ); - let dt = SystemKeywords.getDateFromLocaleString(date, contentLocale); - GBLog.info(`BASIC WEEKDAY contentLocale: ${this.getContentLocaleWithCulture(contentLocale)}`); - GBLog.info(`BASIC WEEKDAY date: ${dt}`); - GBLog.info(dt.toLocaleString(this.getContentLocaleWithCulture(contentLocale), { weekday: 'short' })); + let dt = SystemKeywords.getDateFromLocaleString(date, contentLocale); + GBLog.info(`BASIC WEEKDAY contentLocale: ${this.getContentLocaleWithCulture(contentLocale)}`); + GBLog.info(`BASIC WEEKDAY date: ${dt}`); + GBLog.info(dt.toLocaleString(this.getContentLocaleWithCulture(contentLocale), { weekday: 'short' })); - if (dt) { - if (!(dt instanceof Date)) { - dt = new Date(dt); + if (dt) { + if (!(dt instanceof Date)) { + dt = new Date(dt); + } + let week = dt.toLocaleString(this.getContentLocaleWithCulture(contentLocale), { weekday: 'short' }); + return week.substr(0, 3); } - let week = dt.toLocaleString(this.getContentLocaleWithCulture(contentLocale), { weekday: 'short' }); - return week.substr(0, 3); + return 'NULL'; } - return 'NULL'; -} /** * Returns an object ready to get information about difference in several ways @@ -390,24 +390,24 @@ export class DialogKeywords { * */ public dateDiff(date1, date2, mode) { - let dt1 = date1; - let dt2 = date2; - if (!(dt1 instanceof Date)) { - dt1 = new Date(dt1); + let dt1 = date1; + let dt2 = date2; + if (!(dt1 instanceof Date)) { + dt1 = new Date(dt1); + } + if (!(dt2 instanceof Date)) { + dt2 = new Date(dt2); + } + const diff = new DateDiff(date1, date2); + switch (mode) { + case 'year': return diff.years(); + case 'month': return diff.months(); + case 'week': return diff.weeks(); + case 'day': return diff.days(); + case 'hour': return diff.hours(); + case 'minute': return diff.minutes(); + } } - if (!(dt2 instanceof Date)) { - dt2 = new Date(dt2); - } - const diff = new DateDiff(date1, date2); - switch (mode) { - case 'year': return diff.years(); - case 'month': return diff.months(); - case 'week': return diff.weeks(); - case 'day': return diff.days(); - case 'hour': return diff.hours(); - case 'minute': return diff.minutes(); - } -} /** * Returns specified date week day in format 'Mon'. @@ -417,25 +417,25 @@ export class DialogKeywords { * https://stackoverflow.com/a/1214753/18511 */ public dateAdd(date, mode, units) { - let dateCopy = date; - if (!(dateCopy instanceof Date)) { - dateCopy = new Date(dateCopy); + let dateCopy = date; + if (!(dateCopy instanceof Date)) { + dateCopy = new Date(dateCopy); + } + var ret = new Date(dateCopy); //don't change original date + var checkRollover = function () { if (ret.getDate() != date.getDate()) ret.setDate(0); }; + switch (String(mode).toLowerCase()) { + case 'year': ret.setFullYear(ret.getFullYear() + units); checkRollover(); break; + case 'quarter': ret.setMonth(ret.getMonth() + 3 * units); checkRollover(); break; + case 'month': ret.setMonth(ret.getMonth() + units); checkRollover(); break; + case 'week': ret.setDate(ret.getDate() + 7 * units); break; + case 'day': ret.setDate(ret.getDate() + units); break; + case 'hour': ret.setTime(ret.getTime() + units * 3600000); break; + case 'minute': ret.setTime(ret.getTime() + units * 60000); break; + case 'second': ret.setTime(ret.getTime() + units * 1000); break; + default: ret = undefined; break; + } + return ret; } - var ret = new Date(dateCopy); //don't change original date - var checkRollover = function () { if (ret.getDate() != date.getDate()) ret.setDate(0); }; - switch (String(mode).toLowerCase()) { - case 'year': ret.setFullYear(ret.getFullYear() + units); checkRollover(); break; - case 'quarter': ret.setMonth(ret.getMonth() + 3 * units); checkRollover(); break; - case 'month': ret.setMonth(ret.getMonth() + units); checkRollover(); break; - case 'week': ret.setDate(ret.getDate() + 7 * units); break; - case 'day': ret.setDate(ret.getDate() + units); break; - case 'hour': ret.setTime(ret.getTime() + units * 3600000); break; - case 'minute': ret.setTime(ret.getTime() + units * 60000); break; - case 'second': ret.setTime(ret.getTime() + units * 1000); break; - default: ret = undefined; break; - } - return ret; -} @@ -446,19 +446,19 @@ export class DialogKeywords { * */ public getToLst(array, member) { - if (!array) { - return "" - } - if (array[0] && array[0]['gbarray']) { - array = array.slice(1); - } - array = array.filter((v, i, a) => a.findIndex(t => (t[member] === v[member])) === i); - array = array.filter(function (item, pos) { return item != undefined; }); - array = array.map((item) => { return item[member]; }) - array = array.join(", "); + if (!array) { + return "" + } + if (array[0] && array[0]['gbarray']) { + array = array.slice(1); + } + array = array.filter((v, i, a) => a.findIndex(t => (t[member] === v[member])) === i); + array = array.filter(function (item, pos) { return item != undefined; }); + array = array.map((item) => { return item[member]; }) + array = array.join(", "); - return array; -} + return array; + } /** * Returns the specified time in format hh:dd. @@ -467,29 +467,29 @@ export class DialogKeywords { * */ public getHourFromDate(date) { - function addZero(i) { - if (i < 10) { - i = "0" + i; + function addZero(i) { + if (i < 10) { + i = "0" + i; + } + return i; } - return i; - } - const contentLocale = this.min.core.getParam( - this.min.instance, - 'Default Content Language', - GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') - ); + const contentLocale = this.min.core.getParam( + this.min.instance, + 'Default Content Language', + GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') + ); - let dt = SystemKeywords.getDateFromLocaleString(date, contentLocale); + let dt = SystemKeywords.getDateFromLocaleString(date, contentLocale); - if (dt) { - if (!(dt instanceof Date)) { - dt = new Date(dt); + if (dt) { + if (!(dt instanceof Date)) { + dt = new Date(dt); + } + return addZero(dt.getHours()) + ':' + addZero(dt.getMinutes()); } - return addZero(dt.getHours()) + ':' + addZero(dt.getMinutes()); + return 'NULL'; } - return 'NULL'; -} /** * Returns current time in format hh:dd. @@ -498,22 +498,22 @@ export class DialogKeywords { * */ public async getNow() { - const contentLocale = this.min.core.getParam( - this.min.instance, - 'Default Content Language', - GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') - ); + const contentLocale = this.min.core.getParam( + this.min.instance, + 'Default Content Language', + GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') + ); - const nowUTC = new Date(); - const now = typeof nowUTC === 'string' ? - new Date(nowUTC) : - nowUTC; + const nowUTC = new Date(); + const now = typeof nowUTC === 'string' ? + new Date(nowUTC) : + nowUTC; - const nowText = now.toLocaleString(this.getContentLocaleWithCulture(contentLocale), - { timeZone: process.env.DEFAULT_TIMEZONE }); + const nowText = now.toLocaleString(this.getContentLocaleWithCulture(contentLocale), + { timeZone: process.env.DEFAULT_TIMEZONE }); - return /\b([0-9]|0[0-9]|1?[0-9]|2[0-3]):[0-5]?[0-9]/.exec(nowText)[0]; -} + return /\b([0-9]|0[0-9]|1?[0-9]|2[0-3]):[0-5]?[0-9]/.exec(nowText)[0]; + } /** * Sends a file to a given mobile. @@ -522,9 +522,9 @@ export class DialogKeywords { * */ public async sendFileTo(step, mobile, filename, caption) { - GBLog.info(`BASIC: SEND FILE TO '${mobile}', filename '${filename}'.`); - return await this.internalSendFile(null, mobile, filename, caption); -} + GBLog.info(`BASIC: SEND FILE TO '${mobile}', filename '${filename}'.`); + return await this.internalSendFile(null, mobile, filename, caption); + } /** * Sends a file to the current user. @@ -533,10 +533,10 @@ export class DialogKeywords { * */ public async sendFile(step, filename, caption) { - const mobile = await this.userMobile(step); - GBLog.info(`BASIC: SEND FILE (current: ${mobile}, filename '${filename}'.`); - return await this.internalSendFile(step, mobile, filename, caption); -} + const mobile = await this.userMobile(step); + GBLog.info(`BASIC: SEND FILE (current: ${mobile}, filename '${filename}'.`); + return await this.internalSendFile(step, mobile, filename, caption); + } /** * Defines the current language of the bot conversation. @@ -545,14 +545,14 @@ export class DialogKeywords { * */ public async setLanguage(step, language) { - const user = await this.min.userProfile.get(step.context, {}); + const user = await this.min.userProfile.get(step.context, {}); - const sec = new SecService(); - user.systemUser = await sec.updateUserLocale(user.systemUser.userId, language); + const sec = new SecService(); + user.systemUser = await sec.updateUserLocale(user.systemUser.userId, language); - await this.min.userProfile.set(step.context, user); - this.user = user; -} + await this.min.userProfile.set(step.context, user); + this.user = user; + } /** * Defines the maximum lines to scan in spreedsheets. @@ -561,11 +561,11 @@ export class DialogKeywords { * */ public async setMaxLines(step, count) { - const user = await this.min.userProfile.get(step.context, {}); - user.basicOptions.maxLines = count; - await this.min.userProfile.set(step.context, user); - this.user = user; -} + const user = await this.min.userProfile.get(step.context, {}); + user.basicOptions.maxLines = count; + await this.min.userProfile.set(step.context, user); + this.user = user; + } /** * Defines the FIND behaviour to consider whole words while searching. @@ -574,11 +574,11 @@ export class DialogKeywords { * */ public async setWholeWord(step, on) { - const user = await this.min.userProfile.get(step.context, {}); - user.basicOptions.wholeWord = (on.trim() === "on"); - await this.min.userProfile.set(step.context, user); - this.user = user; -} + const user = await this.min.userProfile.get(step.context, {}); + user.basicOptions.wholeWord = (on.trim() === "on"); + await this.min.userProfile.set(step.context, user); + this.user = user; + } /** * Defines the theme for assets generation. @@ -587,11 +587,11 @@ export class DialogKeywords { * */ public async setTheme(step, theme) { - const user = await this.min.userProfile.get(step.context, {}); - user.basicOptions.theme = theme.trim(); - await this.min.userProfile.set(step.context, user); - this.user = user; -} + const user = await this.min.userProfile.get(step.context, {}); + user.basicOptions.theme = theme.trim(); + await this.min.userProfile.set(step.context, user); + this.user = user; + } /** * Defines translator behaviour. @@ -600,26 +600,26 @@ export class DialogKeywords { * */ public async setTranslatorOn(step, on) { - const user = await this.min.userProfile.get(step.context, {}); - user.basicOptions.translatorOn = (on.trim() === "on"); - await this.min.userProfile.set(step.context, user); - this.user = user; -} + const user = await this.min.userProfile.get(step.context, {}); + user.basicOptions.translatorOn = (on.trim() === "on"); + await this.min.userProfile.set(step.context, user); + this.user = user; + } /** * Returns the name of the user acquired by WhatsApp API. */ public async userName(step) { - return step ? WhatsappDirectLine.usernames[await this.userMobile(step)] : 'N/A'; -} + return step ? WhatsappDirectLine.usernames[await this.userMobile(step)] : 'N/A'; + } /** * OBSOLETE. */ public async getFrom(step) { - return step ? await this.userMobile(step) : 'N/A'; -} + return step ? await this.userMobile(step) : 'N/A'; + } /** @@ -629,8 +629,8 @@ export class DialogKeywords { * */ public async userMobile(step) { - return GBMinService.userMobile(step); -} + return GBMinService.userMobile(step); + } /** * Shows the subject menu to the user @@ -639,8 +639,8 @@ export class DialogKeywords { * */ public async showMenu(step) { - return await step.beginDialog('/menu'); -} + return await step.beginDialog('/menu'); + } /** * Performs the transfer of the conversation to a human agent. @@ -649,8 +649,8 @@ export class DialogKeywords { * */ public async transferTo(step, to: string = null) { - return await step.beginDialog('/t', { to: to }); -} + return await step.beginDialog('/t', { to: to }); + } /** * Hears something from user and put it in a variable @@ -659,91 +659,77 @@ export class DialogKeywords { * */ public async hear(step, promise, previousResolve, kind, ...args) { - function random(low, high) { - return Math.random() * (high - low) + low; - } - const idPromise = random(0, 120000000); - this.min.cbMap[idPromise] = {}; - this.min.cbMap[idPromise].promise = promise; + function random(low, high) { + return Math.random() * (high - low) + low; + } + const idPromise = random(0, 120000000); + this.min.cbMap[idPromise] = {}; + this.min.cbMap[idPromise].promise = promise; - let opts = { id: idPromise, previousResolve: previousResolve, kind: kind, args }; + let opts = { id: idPromise, previousResolve: previousResolve, kind: kind, args }; - if (this.hrOn) { + if (this.hrOn) { - let sleep = ms => { - return new Promise(resolve => { - setTimeout(resolve, ms); - }); - }; + // Waits for next message in HEAR delegated context. - // Waits for next message in HEAR delegated context. + const botId = this.min.botId; + WhatsappDirectLine.state[botId + this.hrOn] = { + promise: promise, previousResolve: previousResolve + }; + } + else { - const mobile = await this.userMobile(step); - while (true) { - if (WhatsappDirectLine.state[mobile] === 3) { - break; + if (previousResolve !== undefined) { + previousResolve(opts); + } else { + await step.beginDialog('/hear', opts); } - sleep(5000); - } - const result = WhatsappDirectLine.lastMessage[this.min.instance.botId + mobile]; - opts = await promise(step, result); - - if (previousResolve !== undefined) { - previousResolve(opts); } } - else { - - if (previousResolve !== undefined) { - previousResolve(opts); - } else { - await step.beginDialog('/hear', opts); - } - } -} /** * Prepares the next dialog to be shown to the specified user. */ public async gotoDialog(step, fromOrDialogName: string, dialogName: string) { - if (dialogName) { - if (dialogName.charAt(0) === '/') { - await step.beginDialog(fromOrDialogName); - } else { - let sec = new SecService(); - let user = await sec.getUserFromSystemId(fromOrDialogName); - if (!user) { - user = await sec.ensureUser(this.min.instance.instanceId, fromOrDialogName, - fromOrDialogName, null, 'whatsapp', 'from', null); + if (dialogName) { + if (dialogName.charAt(0) === '/') { + await step.beginDialog(fromOrDialogName); + } else { + let sec = new SecService(); + let user = await sec.getUserFromSystemId(fromOrDialogName); + if (!user) { + user = await sec.ensureUser(this.min.instance.instanceId, fromOrDialogName, + fromOrDialogName, null, 'whatsapp', 'from', null); + } + await sec.updateUserHearOnDialog(user.userId, dialogName); } - await sec.updateUserHearOnDialog(user.userId, dialogName); + } + else { + await step.beginDialog(fromOrDialogName); } } - else { - await step.beginDialog(fromOrDialogName); - } -} /** * Talks to the user by using the specified text. */ public async talk(step, text: string) { - await this.min.conversationalService['sendTextWithOptions'](this.min, step, text, - this.user.basicOptions.translatorOn, null); -} + const translate = this.user ? this.user.basicOptions.translatorOn : false; + await this.min.conversationalService['sendTextWithOptions'](this.min, step, text, + translate, null); + } private static getChannel(step): string { - if (!step) return 'whatsapp'; - if (!isNaN(step.context.activity['mobile'])) { - return 'webchat'; - } else { - if (step.context.activity.from && !isNaN(step.context.activity.from.id)) { - return 'whatsapp'; + if (!step) return 'whatsapp'; + if (!isNaN(step.context.activity['mobile'])) { + return 'webchat'; + } else { + if (step.context.activity.from && !isNaN(step.context.activity.from.id)) { + return 'whatsapp'; + } + return 'webchat'; } - return 'webchat'; } -} /** @@ -751,49 +737,49 @@ export class DialogKeywords { */ private async internalSendFile(step, mobile, filename, caption) { - // Handles SEND FILE TO mobile, element in Web Automation. + // Handles SEND FILE TO mobile, element in Web Automation. - const page = filename._page; - if (page) { - const gbaiName = `${this.min.botId}.gbai`; - const localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.jpg`); - await filename.screenshot({ path: localName }); + const page = filename._page; + if (page) { + const gbaiName = `${this.min.botId}.gbai`; + const localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.jpg`); + await filename.screenshot({ path: localName }); - const url = urlJoin( - GBServer.globals.publicAddress, - this.min.botId, - 'cache', - Path.basename(localName) - ); + const url = urlJoin( + GBServer.globals.publicAddress, + this.min.botId, + 'cache', + Path.basename(localName) + ); - GBLog.info(`BASIC: WebAutomation: Sending the file ${url} to mobile ${mobile}.`); - await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption); - } - - // Handles Markdown. - - else if (filename.indexOf('.md') > -1) { - GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile ${mobile}.`); - const md = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename); - if (!md) { - GBLog.info(`BASIC: Markdown file ${filename} not found on database for ${this.min.instance.botId}.`); + GBLog.info(`BASIC: WebAutomation: Sending the file ${url} to mobile ${mobile}.`); + await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption); } - await this.min.conversationalService['playMarkdown'](this.min, md, - DialogKeywords.getChannel(step), step, mobile); + // Handles Markdown. - } else { - GBLog.info(`BASIC: Sending the file ${filename} to mobile ${mobile}.`); - const url = urlJoin( - GBServer.globals.publicAddress, - 'kb', - `${this.min.botId}.gbai`, - `${this.min.botId}.gbkb`, - 'assets', - filename - ); + else if (filename.indexOf('.md') > -1) { + GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile ${mobile}.`); + const md = await this.min.kbService.getAnswerTextByMediaName(this.min.instance.instanceId, filename); + if (!md) { + GBLog.info(`BASIC: Markdown file ${filename} not found on database for ${this.min.instance.botId}.`); + } - await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption); + await this.min.conversationalService['playMarkdown'](this.min, md, + DialogKeywords.getChannel(step), step, mobile); + + } else { + GBLog.info(`BASIC: Sending the file ${filename} to mobile ${mobile}.`); + const url = urlJoin( + GBServer.globals.publicAddress, + 'kb', + `${this.min.botId}.gbai`, + `${this.min.botId}.gbkb`, + 'assets', + filename + ); + + await this.min.conversationalService.sendFile(this.min, step, mobile, url, caption); + } } -} } \ No newline at end of file diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index 8c36a8f9..0aae918b 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -175,8 +175,8 @@ export class GBVMService extends GBService { code = `<%\n id = sys().getRandomId() - username = this.userName(step); - mobile = this.userMobile(step); + username = step ? this.userName(step) : sys().getRandomId(); + mobile = step ? this.userMobile(step) : sys().getRandomId(); from = mobile; ubound = function(array){return array.length}; isarray = function(array){return Array.isArray(array) }; @@ -728,7 +728,7 @@ export class GBVMService extends GBService { GBConfigService.get('DEFAULT_CONTENT_LANGUAGE') ); - if (step.context.activity['originalText']) { + if (step && step.context.activity['originalText']) { const entities = await min["nerEngine"].findEntities( step.context.activity['originalText'], contentLocale); diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 8b85de65..473ea229 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -188,8 +188,6 @@ export class GBMinService { }); GBLog.info(`Package deployment done.`); - - } @@ -524,7 +522,7 @@ export class GBMinService { } } catch (error) { - GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error}`); + GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error} ${error.stack}`); } } @@ -1249,6 +1247,8 @@ export class GBMinService { } else if (cmdOrDialogName === '/call') { await GBVMService.callVM(args, min, step, this.deployer); + } else if (cmdOrDialogName === '/callsch') { + await GBVMService.callVM(args, min, null, null); } else { await step.beginDialog(cmdOrDialogName, { args: args }); } diff --git a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts index 090c8aae..6cd3eab8 100644 --- a/packages/whatsapp.gblib/services/WhatsappDirectLine.ts +++ b/packages/whatsapp.gblib/services/WhatsappDirectLine.ts @@ -278,6 +278,18 @@ export class WhatsappDirectLine extends GBService { } } + const botId = this.min.instance.botId; + + const state = WhatsappDirectLine.state[botId + from]; + if ( state) { + WhatsappDirectLine.state[botId + from] = null; + await state.promise(null, message.text); + + return; // Exit here. + }; + + + // Processes .gbapp message interception. await CollectionUtil.asyncForEach(this.min.appPackages, async (e: IGBPackage) => { await e.onExchangeData(this.min, 'whatsappMessage', message); @@ -291,7 +303,9 @@ export class WhatsappDirectLine extends GBService { if (answerText) { await this.sendToDeviceEx(user.userSystemId, answerText, locale, null); + return; // Exit here. + } if (message.type === 'ptt') { @@ -315,14 +329,12 @@ export class WhatsappDirectLine extends GBService { `No momento estou apenas conseguindo ler mensagens de texto.`, null); } } - const botId = this.min.instance.botId; const conversationId = WhatsappDirectLine.conversationIds[botId + from + group]; const client = await this.directLineClient; WhatsappDirectLine.lastMessage[botId + from] = message; - // Check if this message is from a Human Agent itself. if (user.agentMode === 'self') { @@ -543,37 +555,37 @@ export class WhatsappDirectLine extends GBService { let contents = 0; let body = { - to_number: to, - type: "media", - message: url, - text: caption - }; + to_number: to, + type: "media", + message: url, + text: caption + }; - let phoneId = this.whatsappServiceNumber.split(';')[0]; - let productId = this.whatsappServiceNumber.split(';')[1] + let phoneId = this.whatsappServiceNumber.split(';')[0]; + let productId = this.whatsappServiceNumber.split(';')[1] options = { - url: `${this.INSTANCE_URL}/${productId}/${phoneId}/sendMessage`, - method: 'post', - json: true, - body, - headers: { - 'Content-Type': 'application/json', - 'x-maytapi-key': this.whatsappServiceKey, - }, - }; + url: `${this.INSTANCE_URL}/${productId}/${phoneId}/sendMessage`, + method: 'post', + json: true, + body, + headers: { + 'Content-Type': 'application/json', + 'x-maytapi-key': this.whatsappServiceKey, + }, + }; - } - - try { - // tslint:disable-next-line: await-promise - const result = await request.post(options); - GBLog.info(`File ${url} sent to ${to}: ${result}`); - } catch (error) { - GBLog.error(`Error sending file to Whatsapp provider ${error.message}`); - } } + try { + // tslint:disable-next-line: await-promise + const result = await request.post(options); + GBLog.info(`File ${url} sent to ${to}: ${result}`); + } catch (error) { + GBLog.error(`Error sending file to Whatsapp provider ${error.message}`); + } + } + public async sendAudioToDevice(to, url, chatId) { const options = { method: 'POST',