From 56b687792b6fa230f67adcd047011cfa536006cc Mon Sep 17 00:00:00 2001 From: rodrigorodriguez Date: Sun, 19 Mar 2023 20:09:54 -0300 Subject: [PATCH] fix(all): Fixes in production. --- .vscode/launch.json | 1 + gbot.sh | 0 package.json | 1 + packages/basic.gblib/index.ts | 45 +----- .../basic.gblib/services/DialogKeywords.ts | 6 +- packages/basic.gblib/services/GBVMService.ts | 11 +- .../services/KeywordsExpressions.ts | 27 +++- .../basic.gblib/services/SystemKeywords.ts | 28 ++-- .../core.gbapp/services/GBConfigService.ts | 13 +- .../services/GBConversationalService.ts | 1 + packages/core.gbapp/services/GBLogEx.ts | 11 +- packages/core.gbapp/services/GBMinService.ts | 141 +++++++++++------- packages/core.gbapp/services/GBSSR.ts | 44 +++++- packages/default.gbtest/first-test.xlsx | Bin 8419 -> 15604 bytes .../services/WhatsappDirectLine.ts | 43 ++++-- 15 files changed, 212 insertions(+), 160 deletions(-) mode change 100755 => 100644 gbot.sh diff --git a/.vscode/launch.json b/.vscode/launch.json index 9e3fe8b90..bbee18ad4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,6 +15,7 @@ "args": [ "--no-deprecation", "--loader ts-node/esm", + "--openssl-legacy-provider", "--require ${workspaceRoot}/suppress-node-warnings.cjs", ], "skipFiles": [ diff --git a/gbot.sh b/gbot.sh old mode 100755 new mode 100644 diff --git a/package.json b/package.json index ca81449cb..b17f96666 100644 --- a/package.json +++ b/package.json @@ -144,6 +144,7 @@ "punycode": "2.1.1", "puppeteer": "19.6.3", "puppeteer-extra": "3.3.4", + "puppeteer-extra-plugin-minmax": "1.1.2", "puppeteer-extra-plugin-stealth": "2.11.1", "qr-scanner": "1.4.2", "qrcode": "1.5.1", diff --git a/packages/basic.gblib/index.ts b/packages/basic.gblib/index.ts index 95612c7d3..fa0810a94 100644 --- a/packages/basic.gblib/index.ts +++ b/packages/basic.gblib/index.ts @@ -109,50 +109,7 @@ export class GBBasicPackage implements IGBPackage { } public async loadBot(min: GBMinInstance): Promise { const botId = min.botId; - - const opts = { - pingSendTimeout: null, - keepAliveTimeout: null, - listeners: { - unsubscribed(subscriptions: number): void {}, - subscribed(subscriptions: number): void {}, - disconnected(remoteId: string, connections: number): void {}, - connected(remoteId: string, connections: number): void {}, - messageIn(...params): void { - GBLogEx.info(min, '[IN] ' + params); - }, - messageOut(...params): void { - GBLogEx.info(min, '[OUT] ' + params); - } - } - }; - - function getRemoteId(ctx: Koa.Context) { - return '1'; // share a single session for now, real impl could use cookies or some other meaning for HTTP sessions - } - let instances: IGBInstance[]; - instances = await min.core.loadInstances(); - let proxies = {}; - await CollectionUtil.asyncForEach(instances, async instance => { - const proxy = { - dk: new DialogKeywords(), - wa: new WebAutomationServices(), - sys: new SystemKeywords(), - dbg: new DebuggerService(), - img: new ImageProcessingServices() - }; - proxies[instance.botId] = proxy; - }); - - GBServer.globals.server.dk = createRpcServer( - proxies, - createKoaHttpServer(GBVMService.API_PORT, getRemoteId, { prefix: `api/v3` }), - opts - ); - - GBLogEx.info(min, 'API RPC HTTP Server started at http://localhost:' + GBVMService.API_PORT); - - GBServer.globals.debuggers[botId] = {}; + GBServer.globals.debuggers[botId] = {}; GBServer.globals.debuggers[botId].state = 0; GBServer.globals.debuggers[botId].breaks = []; GBServer.globals.debuggers[botId].stateInfo = 'Stopped'; diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index 611e5ea9b..e066629c6 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -551,9 +551,9 @@ export class DialogKeywords { } private async setOption({ pid, name, value }) { - if (this.isUserSystemParam(name)) { - throw new Error(`Not possible to define ${name} as it is a reserved system param name.`); - } + // if (this.isUserSystemParam(name)) { + // throw new Error(`Not possible to define ${name} as it is a reserved system param name.`); + // } let { min, user, params } = await DialogKeywords.getProcessInfo(pid); const sec = new SecService(); await sec.setParam(user.userId, name, value); diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index 0816fcd37..a4481b00c 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -297,11 +297,12 @@ export class GBVMService extends GBService { } public static normalizeQuotes(text: any) { - text = text.replace('¨', '"'); - text = text.replace('“', '"'); - text = text.replace('”', '"'); - text = text.replace('‘', "'"); - text = text.replace('’', "'"); + text = text.replace(/\¨/gm, '"'); + text = text.replace(/\“/gm, '"'); + text = text.replace(/\”/gm, '"'); + text = text.replace(/\‘/gm, "'"); + text = text.replace(/\’/gm, "'"); + return text; } diff --git a/packages/basic.gblib/services/KeywordsExpressions.ts b/packages/basic.gblib/services/KeywordsExpressions.ts index 008ec5d3c..b1e3b9603 100644 --- a/packages/basic.gblib/services/KeywordsExpressions.ts +++ b/packages/basic.gblib/services/KeywordsExpressions.ts @@ -32,6 +32,8 @@ 'use strict'; +import { GBVMService } from "./GBVMService.js"; + /** * Image processing services of conversation to be called by BASIC. */ @@ -292,9 +294,9 @@ export class KeywordsExpressions { keywords[i++] = [ /^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*find\s*(.*)\s*or talk\s*(.*)/gim, ($0, $1, $2, $3) => { - return `${$1} = await sys.find({pid: pid, handle: page, args:[${$2}])\n - if (!${$1}) {s - await dk.talk ({pid: pid, ${$3}})\n; + return `${$1} = await sys.find({pid: pid, handle: page, args:[${$2}]})\n + if (!${$1}) { + await dk.talk ({pid: pid, text: ${$3}})\n; return -1; } `; @@ -601,7 +603,12 @@ export class KeywordsExpressions { keywords[i++] = [ /^\s*(talk)(\s*)(.*)/gim, ($0, $1, $2, $3) => { - if ($3.substr(0, 1) !== '"') { + $3 = GBVMService.normalizeQuotes($3); + + // Uses auto quote if this is a frase with more then one word. + + if (/\s/.test($3) && $3.substr(0, 1) !== '"') { + $3 = `"${$3}"`; } return `await dk.talk ({pid: pid, text: ${$3}})`; @@ -755,15 +762,19 @@ export class KeywordsExpressions { ]; keywords[i++] = [ - /^\s*save\s*(.*)\s*as\s*(.*)/gim, + /^\s*save\s*(\w+)\s*as\s*(.*)/gim, ($0, $1, $2, $3) => { return `await sys.saveFile({pid: pid, file: ${$2}, data: ${$1}})`; } ]; + keywords[i++] = [ - /^\s*(save)(\s*)(.*)/gim, - ($0, $1, $2, $3) => { - return `await sys.save({pid: pid, args: [${$3}]})`; + /^\s*(save)(\s*)(.*\.xlsx)(.*)/gim, + ($0, $1, $2, $3, $4) => { + $3 = $3.replace (/\'/g, "") + $3 = $3.replace (/\"/g, "") + $4 = $4.substr(2) + return `await sys.save({pid: pid,file: "${$3}" , args: [${$4}]})`; } ]; diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index 92fa15e65..40f7e6798 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -236,6 +236,7 @@ export class SystemKeywords { const gbaiName = DialogKeywords.getGBAIPath(min.botId); const browser = await GBSSR.createBrowser(null); const page = await browser.newPage(); + await page.minimize(); // Includes the associated CSS related to current theme. @@ -544,7 +545,7 @@ export class SystemKeywords { } try { - data = GBServer.globals.files[data].data; + data = GBServer.globals.files[data].data; // TODO await client.api(`${baseUrl}/drive/root:/${path}/${file}:/content`).put(data); } catch (error) { if (error.code === 'itemNotFound') { @@ -562,9 +563,8 @@ export class SystemKeywords { * @exaple SAVE "customers.xlsx", name, email, phone, address, city, state, country * */ - public async save({ pid, args }): Promise { + public async save({ pid,file, args }): Promise { const { min, user } = await DialogKeywords.getProcessInfo(pid); - const file = args[0]; args.shift(); GBLog.info(`BASIC: Saving '${file}' (SAVE). Args: ${args.join(',')}.`); let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min); @@ -589,7 +589,7 @@ export class SystemKeywords { const address = `A2:${this.numberToLetters(args.length - 1)}2`; for (let index = 0; index < args.length; index++) { let value = args[index]; - if (value && this.isValidDate(value)) { + if (value && await this.isValidDate({pid, dt:value})) { value = `'${value}`; } body.values[0][index] = value; @@ -699,8 +699,8 @@ export class SystemKeywords { // MAX LINES property. - let maxLines; - if (user && params && params.maxLines) { + let maxLines = 5000; + if (params && params.maxLines) { if (params.maxLines.toString().toLowerCase() !== 'default') { maxLines = Number.parseInt(params.maxLines).valueOf(); } @@ -718,7 +718,7 @@ export class SystemKeywords { page = WebAutomationServices.getPageByHandle(handle); } - if (page['$eval'] && WebAutomationServices.isSelector(file)) { + if (handle &&page['$eval'] && WebAutomationServices.isSelector(file)) { const container = page['frame'] ? page['frame'] : page; const originalSelector = file; @@ -857,10 +857,10 @@ export class SystemKeywords { if (this.isValidHour(filter.value)) { filter.dataType = fixed ? fixed : 'hourInterval'; - } else if (this.isValidDate(filter.value)) { + } else if (await this.isValidDate({pid, dt: filter.value})) { filter.value = SystemKeywords.getDateFromLocaleString(pid, filter.value, contentLocale); filter.dataType = fixed ? fixed : 'date'; - } else if (this.isValidNumber(filter.value)) { + } else if (await this.isValidNumber({pid, number: filter.value})) { filter.value = Number.parseInt(filter.value); filter.dataType = fixed ? fixed : 'number'; } else { @@ -893,7 +893,7 @@ export class SystemKeywords { switch (filter.dataType) { case 'string': const v1 = GBConversationalService.removeDiacritics(result.toLowerCase().trim()); - const v2 = GBConversationalService.removeDiacritics(filter.toLowerCase().trim()); + const v2 = GBConversationalService.removeDiacritics(filter.value.toLowerCase().trim()); switch (filter.operator) { case '=': @@ -1003,7 +1003,7 @@ export class SystemKeywords { const propertyName = header[colIndex]; let value = xlRow[colIndex]; if (value && value.charAt(0) === "'") { - if (this.isValidDate(value.substr(1))) { + if (await this.isValidDate({pid, dt:value.substr(1)})) { value = value.substr(1); } } @@ -1650,7 +1650,7 @@ export class SystemKeywords { const propertyName = header[colIndex]; let value = xlRow[colIndex]; if (value && value.charAt(0) === "'") { - if (this.isValidDate(value.substr(1))) { + if (await this.isValidDate({pid, dt:value.substr(1)})) { value = value.substr(1); } } @@ -1702,13 +1702,13 @@ export class SystemKeywords { } } } else { - let args = [file]; + let args = []; let keys = Object.keys(row); for (let j = 0; j < keys.length; j++) { args.push(row[keys[j]]); } - await this.save({ pid, args }); + await this.save({ pid,file, args }); adds++; } } diff --git a/packages/core.gbapp/services/GBConfigService.ts b/packages/core.gbapp/services/GBConfigService.ts index 9df157c31..b7257e2df 100644 --- a/packages/core.gbapp/services/GBConfigService.ts +++ b/packages/core.gbapp/services/GBConfigService.ts @@ -43,10 +43,10 @@ import * as en from 'dotenv-extended'; * Base configuration for the server like storage. */ export class GBConfigService { - public static getBoolean (value: string): boolean { + public static getBoolean(value: string): boolean { return (this.get(value) as unknown) as boolean; } - public static getServerPort (): string { + public static getServerPort(): string { if (process.env.PORT) { return process.env.PORT; } @@ -57,7 +57,7 @@ export class GBConfigService { return '4242'; } - public static init (): any { + public static init(): any { try { en.load({ encoding: 'utf8', @@ -78,7 +78,7 @@ export class GBConfigService { } } - public static get (key: string): string | undefined { + public static get(key: string): string | undefined { let value = GBConfigService.tryGet(key); if (value === undefined) { @@ -155,6 +155,9 @@ export class GBConfigService { case 'ENABLE_SPELLING_CHECKER': value = false; break; + case 'DEV_GBAI': + value = undefined; + break; default: GBLog.warn(`Invalid key on .env file: '${key}'`); break; @@ -164,7 +167,7 @@ export class GBConfigService { return value; } - public static tryGet (key: string): any { + public static tryGet(key: string): any { let value = process.env[`container:${key}`]; if (value === undefined) { value = process.env[key]; diff --git a/packages/core.gbapp/services/GBConversationalService.ts b/packages/core.gbapp/services/GBConversationalService.ts index ceab62ec4..3a6e72668 100644 --- a/packages/core.gbapp/services/GBConversationalService.ts +++ b/packages/core.gbapp/services/GBConversationalService.ts @@ -900,6 +900,7 @@ export class GBConversationalService { } public async translate(min: GBMinInstance, text: string, language: string): Promise { + const translatorEnabled = () => { if (min.instance.params) { const params = JSON.parse(min.instance.params); diff --git a/packages/core.gbapp/services/GBLogEx.ts b/packages/core.gbapp/services/GBLogEx.ts index a57db04f5..aade79265 100644 --- a/packages/core.gbapp/services/GBLogEx.ts +++ b/packages/core.gbapp/services/GBLogEx.ts @@ -77,10 +77,11 @@ export class GBLogEx { */ public static async log(instance: IGBInstance, kind: string, message: string): Promise { message = message ? message.substring(0, 1023) : null; - return await GuaribasLog.create({ - instanceId: instance ? instance.instanceId : 1, - message: message, - kind: kind - }); + // return await GuaribasLog.create({ + // instanceId: instance ? instance.instanceId : 1, + // message: message, + // kind: kind + // }); + return null; } } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index ecc5f7b45..a358a7db9 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -48,6 +48,11 @@ import mkdirp from 'mkdirp'; import Fs from 'fs'; import arrayBufferToBuffer from 'arraybuffer-to-buffer'; import { NlpManager } from 'node-nlp'; +import Koa from 'koa'; +import cors from '@koa/cors'; +import { createRpcServer } from '@push-rpc/core'; +import { createHttpKoaMiddleware } from '@push-rpc/http'; +import { HttpServerOptions } from '@push-rpc/http/dist/server.js'; import { AutoSaveStateMiddleware, BotFrameworkAdapter, @@ -88,6 +93,11 @@ import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js'; import Path from 'path'; import { GBSSR } from './GBSSR.js'; import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords.js'; +import { GBLogEx } from './GBLogEx.js'; +import { WebAutomationServices } from '../../basic.gblib/services/WebAutomationServices.js'; +import { createKoaHttpServer } from '../../basic.gblib/index.js'; +import { DebuggerService } from '../../basic.gblib/services/DebuggerService.js'; +import { ImageProcessingServices } from '../../basic.gblib/services/ImageProcessingServices.js'; /** * Minimal service layer for a bot and encapsulation of BOT Framework calls. @@ -156,6 +166,7 @@ export class GBMinService { // Calls mountBot event to all bots. let i = 1; + if (instances.length > 1) { this.bar1 = new cliProgress.SingleBar( { @@ -168,45 +179,65 @@ export class GBMinService { this.bar1.start(instances.length, i, { botId: 'Boot' }); } - const throttledPromiseAll = async promises => { - const MAX_IN_PROCESS = 20; - const results = new Array(promises.length); - - async function doBlock(startIndex) { - // Shallow-copy a block of promises to work on - const currBlock = promises.slice(startIndex, startIndex + MAX_IN_PROCESS); - // Await the completion. If any fail, it will throw and that's good. - const blockResults = await Promise.all(currBlock); - // Assuming all succeeded, copy the results into the results array - for (let ix = 0; ix < blockResults.length; ix++) { - results[ix + startIndex] = blockResults[ix]; + + await CollectionUtil.asyncForEach(instances, (async instance => { + try { + await this['mountBot'](instance); + } catch (error) { + GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`); + } + finally { + if (this.bar1) { + this.bar1.update(i++, { botId: instance.botId }); } } + }).bind(this)); - for (let iBlock = 0; iBlock < promises.length; iBlock += MAX_IN_PROCESS) { - await doBlock(iBlock); + if (this.bar1) { + this.bar1.stop(); + } + const opts = { + pingSendTimeout: null, + keepAliveTimeout: null, + listeners: { + unsubscribed(subscriptions: number): void { }, + subscribed(subscriptions: number): void { }, + disconnected(remoteId: string, connections: number): void { }, + connected(remoteId: string, connections: number): void { }, + messageIn(...params): void { + GBLogEx.info(0, '[IN] ' + params); + }, + messageOut(...params): void { + GBLogEx.info(0, '[OUT] ' + params); + } } - return results; }; - await throttledPromiseAll( - instances.map( - (async instance => { - try { - await this['mountBot'](instance); + function getRemoteId(ctx: Koa.Context) { + return '1'; // share a single session for now, real impl could use cookies or some other meaning for HTTP sessions + } - if (this.bar1) { - this.bar1.update(i++, { botId: instance.botId }); - } - } catch (error) { - GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`); - } - }).bind(this) - ) + let proxies = {}; + await CollectionUtil.asyncForEach(instances, async instance => { + const proxy = { + dk: new DialogKeywords(), + wa: new WebAutomationServices(), + sys: new SystemKeywords(), + dbg: new DebuggerService(), + img: new ImageProcessingServices() + }; + proxies[instance.botId] = proxy; + }); + + GBServer.globals.server.dk = createRpcServer( + proxies, + createKoaHttpServer(GBVMService.API_PORT, getRemoteId, { prefix: `api/v3` }), + opts ); - if (this.bar1) { - this.bar1.stop(); - } + + GBLogEx.info(0, 'API RPC HTTP Server started.'); + + // // Loads schedules. // GBLog.info(`Preparing SET SCHEDULE dialog calls...`); @@ -255,7 +286,7 @@ export class GBMinService { /** * Unmounts the bot web site (default.gbui) secure domain, if any. */ - public async unloadDomain(instance: IGBInstance) {} + public async unloadDomain(instance: IGBInstance) { } /** * Mount the instance by creating an BOT Framework bot object, @@ -297,11 +328,11 @@ export class GBMinService { if (Fs.existsSync(packagePath)) { await this.deployer['deployPackage2'](min, user, packagePath); } - + const gbai = DialogKeywords.getGBAIPath(min.botId); let dir = `work/${gbai}/cache`; - const botId = gbai.replace(/\.[^/.]+$/, ""); - + const botId = gbai.replace(/\.[^/.]+$/, ""); + if (!Fs.existsSync(dir)) { mkdirp.sync(dir); } @@ -332,7 +363,7 @@ export class GBMinService { // Loads Named Entity data for this bot. - await KBService.RefreshNER(min); + // TODO: await KBService.RefreshNER(min); // Calls the loadBot context.activity for all packages. @@ -452,7 +483,7 @@ export class GBMinService { if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) { if (!(await min.whatsAppDirectLine.check(min))) { - const error = `WhatsApp API lost connection.`; + const error = `WhatsApp API lost connection for: ${min.botId}.`; GBLog.error(error); res.status(500).send(error); @@ -532,9 +563,8 @@ export class GBMinService { min.instance.authenticatorTenant, '/oauth2/authorize' ); - authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${ - min.instance.marketplaceId - }&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`; + authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId + }&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`; GBLog.info(`HandleOAuthRequests: ${authorizationUrl}.`); res.redirect(authorizationUrl); }); @@ -743,18 +773,16 @@ export class GBMinService { await min.whatsAppDirectLine.setup(true); } else { const minBoot = GBServer.globals.minBoot as any; - if (minBoot.whatsappServiceKey) { - min.whatsAppDirectLine = new WhatsappDirectLine( - min, - min.botId, - min.instance.whatsappBotKey, - minBoot.instance.whatsappServiceKey, - minBoot.instance.whatsappServiceNumber, - minBoot.instance.whatsappServiceUrl, - group - ); - await min.whatsAppDirectLine.setup(false); - } + min.whatsAppDirectLine = new WhatsappDirectLine( + min, + min.botId, + min.instance.whatsappBotKey, + minBoot.instance.whatsappServiceKey, + minBoot.instance.whatsappServiceNumber, + minBoot.instance.whatsappServiceUrl, + group + ); + await min.whatsAppDirectLine.setup(false); } // Setups default BOT Framework dialogs. @@ -853,7 +881,7 @@ export class GBMinService { // Default activity processing and handler. - const handler = async context => { + const handler = async context => { // Handle activity text issues. if (!context.activity.text) { @@ -1035,9 +1063,8 @@ export class GBMinService { await this.processEventActivity(min, user, context, step); } } catch (error) { - const msg = `ERROR: ${error.message} ${error.error ? error.error.body : ''} ${ - error.error ? (error.error.stack ? error.error.stack : '') : '' - }`; + const msg = `ERROR: ${error.message} ${error.error ? error.error.body : ''} ${error.error ? (error.error.stack ? error.error.stack : '') : '' + }`; GBLog.error(msg); await min.conversationalService.sendText( @@ -1053,7 +1080,7 @@ export class GBMinService { try { await adapter['processActivity'](req, res, handler); } catch (error) { - if (error.code === 401){ + if (error.code === 401) { GBLog.error('Calling processActivity due to Signing Key could not be retrieved error.'); await adapter['processActivity'](req, res, handler); } diff --git a/packages/core.gbapp/services/GBSSR.ts b/packages/core.gbapp/services/GBSSR.ts index d358aea2d..f196a89c7 100644 --- a/packages/core.gbapp/services/GBSSR.ts +++ b/packages/core.gbapp/services/GBSSR.ts @@ -125,9 +125,11 @@ export class GBSSR { }; } + public static async createBrowser(profilePath): Promise { const opts = this.preparePuppeteer(profilePath); puppeteer.use(hidden()); + puppeteer.use(require("puppeteer-extra-plugin-minmax")()); const browser = await puppeteer.launch(opts); return browser; } @@ -143,6 +145,8 @@ export class GBSSR { try { const page = await browser.newPage(); + await page.minimize(); + await page.setUserAgent( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36' ); @@ -277,35 +281,61 @@ export class GBSSR { req.originalUrl ); - // Reads from static HTML when a bot is crawling. + // Tries to find botId from URL. - const botId = - req.originalUrl || req.originalUrl === '/' ? req.originalUrl.substr(1) : GBServer.globals.minInstances[0].botId; + const minBoot = GBServer.globals.minInstances[0]; + let botId = + req.originalUrl && req.originalUrl === '/' ? + minBoot.botId : + /\/([A-Za-z0-9\-\_]+)\/*/.exec(req.originalUrl)[1] let min: GBMinInstance = req.url === '/' - ? GBServer.globals.minInstances[0] - : GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0]; + ? minBoot + : GBServer.globals.minInstances.filter(p => p.instance.botId.toLowerCase() === botId.toLowerCase())[0]; + if (!min) { + min = req.url === '/' + ? minBoot + : GBServer.globals.minInstances.filter(p => p.instance.activationCode.toLowerCase() === botId.toLowerCase())[0]; + } + if (!min) { + botId = minBoot.botId; + } + let path = DialogKeywords.getGBAIPath(botId, `gbui`); + // Checks if the bot has an .gbui published or use default.gbui. + + if (!Fs.existsSync(path)) { + path = DialogKeywords.getGBAIPath(minBoot.botId, `gbui`); + } + const url = req.url.replace(`/${botId}`, ''); + if (min && req.originalUrl && prerender && exclude) { + + // Reads from static HTML when a bot is crawling. + path = Path.join(process.env.PWD, 'work', path, 'index.html'); const html = Fs.readFileSync(path, 'utf8'); res.status(200).send(html); return true; } else { + + // Servers default.gbui web application. + path = Path.join( process.env.PWD, GBDeployer.deployFolder, GBMinService.uiPackage, 'build', - min ? `index.html` : req.url + url === '/' || url === '' ? `index.html` : url ); if (Fs.existsSync(path)) { if (min) { let html = Fs.readFileSync(path, 'utf8'); html = html.replace(/\{botId\}/gi, min.botId); - html = html.replace(/\{theme\}/gi, min.instance.theme); + html = html.replace(/\{theme\}/gi, min.instance.theme ? min.instance.theme : + 'default.gbtheme'); html = html.replace(/\{title\}/gi, min.instance.title); res.send(html).end(); } else { diff --git a/packages/default.gbtest/first-test.xlsx b/packages/default.gbtest/first-test.xlsx index 237d0f2068f8db3a0cb70a8473f0bb696c08b50e..a6bad648974205b6aa8bcb1d062257f544ba4b08 100644 GIT binary patch delta 6899 zcmai3bySq!x*oc_8M;KeyPJWLkW|2-1?fh>Vd!p^W4Yx=zd{sD|d13L{S;W5JAYhSfAs&Y+EX5=Ul@lk)Ch?Rn`I5r zxR;tkx@Ubd)?!1IRHOUUwg93bC$gQFcdDX6klyPMjrKa?25-yA0D}7UQ*f+v9}lJc zk%(p!1$0wSGthf}pVLf21M*6_0sY(g0ffsYv-Voqzl{kiKhgT#>y9t4Azgk|Ao;|U z(W(U(yDD0EdWJ=fE*&ou`ubzqT~S$J<#DdXv!J8|Jmq{4N{j`8-E!*sUQ3i!<>}+RK7FY9P9j@kIw8P529bu~5 z#4}FlqU1JxN!^y&0-+|1lCIfg)2y_f@x+OVcCSeF;bFV@P{MM4e&2=RIRmp+{&`SUYW7SvRgR+RqFd9rsm z_vaVIPS#@mpU!bKe{#D&U@uZtmFj<=-tb&EBw_|KnwBD^lhC?$Wq++H-6uqvIfIsH z;-Fm{IW7%AT^tK!v{V)G+gHF-Tpk_&ZK)IV&Bqz~wHzyWKHP`#j zWxcMLuD1=K8R!$_4D3^zNiY`A`|R&9DO{-ZbVA~|EhBf=%7n27k=M8+? zO2I_(b!EP}TD>%5S8n;65v5Ui9({C6bKY-87HNj}p|#tV5mHfH}0RU>iLNY%+5S5|uGay-x>NB)01+3A-hj8$qJH`#CNiR>b zIS*c@J$+6eyq%L^$E2hT{p&+KvUyXJmX~X+e1aPRc_RsP4j(j!WjZX^D>u|h-O&wN z3*V-0IA0!rM6p#HBCqfyXE{W=6ls0`rA_WNyGd8eP68TPbkeNSVi95aGd^tQSr}gG zgl`dh$a^Sp&V-*nOl{qV`{phB=mVj->V$>EC^B2$Wwfo~FV$Q?Jgo=xxJD9|j0smF zQh}R8hH^=FJvxw$wYJ;aq_eBQjS)W=AXcGTjPW>O`ZNu=g#|B^u~SJP#6m1tJj_Zx zOl#}h2xY8?zf>DH)j0h$iEo{OEnRk9ee03?`7%(buD#hb3H{k-fe$M^dG`^9#Dlv= zmF&H+J>XA&t7E|BB~H#j!R1(AIDWl|4FDjE{!|WjfTgFqhqI%RqXVyh*-6JHj~ILJ&*NbRkw1&lQyWX$ zD!psR31sLbP-oe+5y&y4<3WBKeY@1l13xJ1=9$V>PeOOCr_M0!Q)4EIYiD?F5-YI# z?RZ@4aM`@2$5lyPN%V~$Jn)@WxRB9JfH1Y4q}~nm$=nIn{(!v)$+`mu#Q!Dy^uR_~ z06z>18WU=5)HfyYF)P$Pz*6#fjx^2YZ0*cT+E{be^Yb#cz3r)%C`+$;O<8t^rvf1> z^#l{V&{v$%&@%yp<`Aa+K6@BOB+74!!Q6d(8)}*51G9PPXY*+>a$izV%3GBhlLz!N zy;=qO7<4{-B(`ax{>BUG!J5$74q2S{`sZ^L%|4Ru^f>PjCITHH0~SW2{V_tNYt(YB zr*gV+H<=SGE`p$m@oRdhkGEQTNj|8E-IpchKIVQKz}trKB)u1C0dk^sxTCoVuU-R5^0phnxU`q?B{Gakt-&^-EkTPi56a0?qjo)(j4E28 zSj#&X$hjdQmz?(?!n#Tf1c0oi@QseOKoij5EN+m>QEQaq^Cju1F=kaWzWE@W&;ljS zah9GZvFU?S4mt{LP*jiWXW0CJ5uOMc%WPH%R$qCi0?q=S7=+L(v_9>;2WJdLJ-0LT z(0yy)$ARnu1+=4#SuIF?m(%tlGB^T?Uvww1{UIrWB?4^*Tw_VMtbC$RwICC0ev4N! z@41K9{oVI=I6v8$fxuymBobX78pChfM*m%vSbAdL^hA!~v)`gVxdl|@6x`q0QzuQ( z+W0m-BW?ehJWOrXyV#<3A-|hir>z~oJC0A^Q<^YkW&b5pXFVfT9d2?f*PS2qW6|ZK zgZ`1KOJ`vd4~(@z{je}g^{R)JQ*J>rJ%a~f7wkBU@c|#TDdq5wt+s!>*<^AyWUD@& zE2om~CspA6oIJqix4_+imPmg{v{-8;0ffq9p+U_Q!7qCV2}(?|=8D`iTvEoEcnB0< zWPV3()+Fb0tycM{2}_gTNbI(U3WdX&F%>t$YTlHawJ|J)Z|jp*AwRN=M32dp*G*Dl z*ZWXmjLBUvaU!F-`YcW-s_rY^h%ua%%{L;2ag(Ag3odM`Zv+90?Z!Q-m;6(}lJPz_erwP>=Jatlm-#F^2q#>rwnOa!=A@L3C(NQH&jN%^f^tpLtnH^_j(#TK zN~2Th+RRRg-K;lC=F@#zj_0x z!%VXcm@{4%7|7GWLz`%Mfx7J6pBAJSzH8Sl^=a?Ch*>Xlc*6c2>LGU#dtbkW_IQJ) zMf$+wyK}YEsb;~QC|nTM{*ZrsXYJ(9Vh#E}UCa%Ot1D(ug4z}oRU}4DR7%Yk*VV2Z z@^wc~Oo_DyCtQ-uMZebGa9)?oM)s}H_Y*=e%GouM*6o_vP?@5a?&gBhl%gDXvz~jlIk2dCBnfR%cgms=en)w6J*yM%nm;5?%qQ5rp;Ve6Akd?@TCfsp2f<>`-ijDfZ|v>pLMn z4e41TXIzUJT@2&*a1?DhuNJZ%XfEenAJD)hJMuA|*F#_zJZ=ul4IU2iz^;4l4^`{t z^!f+9%5WxgEwel)$B4gn+oLe66;MBqBnbxzXYxX4w}-U zbtWpej?=VLaPyapvQ`66c^>V5e?gIuCa-LlNjs!Ao&Cu5G-9FZd&%aJOj3$Z!+`iC z_}g?JGdggQM$X5vY6w(0|{JFBh- zs5_tA1o}74$kB&j3D_MUNF^;PYe;+QM`Nu#X#1V!R%InTb>b_=*~W%FOtN>aohUoj z^Fv&6-I)41JSBc$(`*KfX`P~U zdY&Kq?JM%TYg_2W6*e2Uc*zhuqJjx{`IS(p@7?RRaV=%ZP&Fagb*>?U!SFb=P?szz z(~wT;?gKr}iseS8At@jG3@j$x)-Dj>PBiu_?8!D@_dsv}5h^2FqF27BufYav1 z5bp|qPTYvX9aMJ%UYuvp7;x|CE0%ss=0v5;zv(Q#5taRDSb2W{n&p@fb(xBOM#e`} zLcK`LJ>aBy{Wry#PRj35A94@Jm16x6sQv^k#$MGdllh zI;6+0sPN87;h^u0a$cwF1dhd#R~4T^jg-lpMrZXH{fba|Wf{eMWS>;tf(E{9KGoW- zG9O7zKL$h%qhDfd-7GMZCAxRusmz^aaQoc6Uj#koCH{5U5!??eS;8LjZ==E7qep4 z8qE;w^~PyH381ZX>PWQ| z%k4=O<=~2WWl_b6{GQw!2Q%e62ujLRvKFWXzpZQvO1pMD%?|p83;&*}TiZH34E3_I z)xNK*hTXp+kzqU-&Q~vSuAEs-{TOM6P?a_|dvEsRDNPvp9By$5Pet6*3fGGIw(Rvx z6v49x;T()}QOxJ~63F2~=}#iGh|io_(#W)WgDX;(eaC!(piqqC{?3{)0|zSHVGj3( zki+gb?)Z&#%o4sj(*}=(7G)ji^iLsrnzP+7`8kBmBWw|2%eOGmHeT_maVn2<@02aK zDZn)+W>W}CuKv|EmF)aA`hz}vVj=uV=ga5yxfv-EF&M#x6cSF?h7N~!C_n3DRu5V6 z=Us>vn;p?;&;c-!{!u{Q!G&;6D z=YApVp1@w~W})<|LkZW>2FdF}B@w>J;+&a1HrzB$5aqB{K22qcK)i&pcLVdTr>V2F z#}7xjbMp#CX9oH!^r_1X5d2OAFWCD+`GA~nh@R-nq7kBJ@gGTP8W4$RM{k4pyvwXu zz-f7Q+7DgC`AL>nBKd7nGlJ|O!YKc%7tnTdc5xT@t0BOR?X>UaBUCyJ{So}Rm1(fY zicnu4?nVZe;5TaR)Ky?OS$;jqcMMs2?-!~p6n-#waqadl#=U12tkGO;*gGlYNAp=0Sywl7CKVoE zN$|2J(EbkTCs&U45DVr61kZVd{deE?aKQ8flIQc{q?-@m z?iE_PL2jg?8=`{6E`?R%uZNnE(GJHE79BWYw$C1?`pLhGeR2Kf7VVc`o)~q%l1GS* z24WEO-+n3hSNK&XwL5h)kg7akwdkh=-u2Yd>Kg-J=}LO^xA)C5lX-XsYjI_Ld~ zSlFSz>iLqFcW&87pxB$L9YU~fJrZ-})Ys1i54D?ATHl*y_RgW1jID_BoBP*!JjFG) z!#uJG$+)(f=`wcKR}0CB)Cb`(7-yzgg>|qJWc%xk;X&Qcu1M;upVfYi^z7G&Nt*3m zKTeHpID!F@&Zn4U6hAaRE86So_F2{6h-`&)>{nrZdO&wtRlg<_jD_KJLB#XseNIRP zNI6;|&`LK7Rx%&;Rr8g}hHt4%kE9;Ef#4wJ*C5cykbTEIqZYqq{YY(g-v|9lA0*Lb zn={!@8zAYu$MBa=_r7jP6Il4Cm$rJUunyI!-XD{EfFewGG|K{GNZ+xt@)3cV?1D z3}K62GV>m;i_IGrYgnUL!2{h1#|w`xGE1eWRV}SN%g-kEz7E3N2){}~7zrYgSvgz&5_H~wGFn{|5Dy8O0Co=M!wox3KBF&On51No*`EIE$Y+u+!88h)G*2pXbU|Rh)k1zCg~rPhP;_65Zr-ci z>w-;as{NZF4UK@nh(<%pRE9}<{AJ%Ahr8%Kz1A-o=aT~Bi%i!r-f{}BZMPfaP;32A zLgEiLtVbP^gyc2pa>y(6H}HY8Qwo(yi9Jge;OYb3)cOa0q3=E7B<4M`Wn!k$7CQI= zMgSxw*p@!mg5f-0B=c<4yUJ>fJY{PYdPypr+XfDSmffX1WB-4$zuz%((f=nsf`3bo z`7i15_$fWZ>Xr)$l9kCcT+BNz|dZd3!&uRE_Qw2R24Lj9#COIja>O-}qj;)=G zHiYy{S{Z_#t_0zRui8yQSL{o8j)(3Zb| zV`gVG9v-4epIjY$SS0`e?(R?k+8Rj6+<^b>twORboha77XVl4MbdK2n8Nb%i(Z5AX zMyJQ;{&Sd!h^l{oz;uAWM~g}Hq|iUhtAGC+@gw;D?||Qmt)B|`YcBrxZvU)aeqSq+ z^Y^uWmTdp3Ws;HTNx1*41b)ZmbN!7IKx|sz&*b|%Ad>rUz^@1K|D^h78v7lU&+|L# zKU9AeA^$7YKa<4oYnAc+zSd8wztl@xM v`29~IK>&3B44dBpIl{j`=08+_ZSr4K(Gc&j00=K61xTO)0L6&8Gyw2FQqdM6 delta 1057 zcmexT`Pk7iz?+#xgn^BLgMooTks;~b+>AIz28IbN3=F~y98A&9`FSO&c_r~7l?AEA zv3eD`ISPwdm^2nJFm1lb{ETs8fK>gODX0Ao8wj|5_xR)dMAz%iCI=4Fw@t@|v;yr8 z9GQGdE)lL2YzAq1T9Xjye#neqVSchOwH=J&yRIIS-O>~?}(MfEe%kN2-Zvr+FA5# zy7#_fjUC2U6Ox(k8MIB<%XjzOeYV~E%;kJdq&BVW`m!qO*o18D{WUQ)Rr@viy1xYc z+GQr15w9CP&!JJV>Cz2`fb8xqVrz}^&etBX7hN3XbNa&}g}c919}3GHxi6ivYhM3^ z6h8^2T%89?kI!@Qw=~yks#|{IV@+`uS_FG|fR*4G1( zm{Bpw*Z;5qPuqKsKkX;JU%fj)z{$JZ(POt_NL_>H9saGoi&doW?pK!)2$5=LcCX)C z_vh5@yEeVAPAGnRWU{7PNW@xsTlw0y>Awm~*|pS)rnwcad3Z#y?CRI6-)6ddRce&& z?blkpW5q)6llPU~E`M~{C~#gcT#8e8sZ5)g?aapfsAIm7_mY0BW4!7V{B~{IhVAAH zUQIqfyZ-vLWiNT{J1l+PT$(9*qBtr2=DL~_If`F@N`(ezSY~cWnpb3{R2iR=bKtYf z?ES)jYjpkQoCs1f5&B_t-u<}hg0J;aTTDKlo?Cguob&MN6CX}Cb<3}~#|R3a&8OIu znFSi{rcD0~45VGaK$2qMV4VDyQ)csRQ#Qu>H9@}KM+^k^a{p^LD4$&>DtNO*U+GQg zYkrQCTQqO0DH_*(xi77?D>mYqw?1=zTjl$+$IHH(@;zb}{(4Y*MVAmum2l2`Yu5a; zpU*OLB)wfL*W}JBEcE8p>(y_$`DPUh@3fnALT8?c#j_t8s*>%Cmnpe?*?FnWB -1 - ? 'maytapi' - : whatsappServiceKey !== 'internal' - ? 'graphapi' - : 'chatapi'; + ? 'maytapi' + : whatsappServiceKey !== 'internal' + ? 'graphapi' + : 'chatapi'; this.groupId = groupId; } @@ -172,7 +172,7 @@ export class WhatsappDirectLine extends GBService { }); client.on('ready', async () => { GBLog.verbose(`GBWhatsApp: Emptying chat list for ${this.botId}...`); - + // TODO: await client.pupPage['minimize'](); // Keeps the chat list cleaned. const chats = await client.getChats(); await CollectionUtil.asyncForEach(chats, async chat => { @@ -192,8 +192,15 @@ export class WhatsappDirectLine extends GBService { }); client.initialize(); }; - createClient.bind(this)(); + if (setUrl){ + createClient.bind(this)(); + } + else + { + this.customClient = minBoot.whatsAppDirectLine.customClient; + } setUrl = false; + break; case 'chatapi': options = { @@ -650,8 +657,7 @@ export class WhatsappDirectLine extends GBService { await this.printMessages(response.obj.activities, conversationId, from, fromName); } catch (err) { GBLog.error( - `Error calling printMessages on Whatsapp channel ${err.data === undefined ? err : err.data} ${ - err.errObj ? err.errObj.message : '' + `Error calling printMessages on Whatsapp channel ${err.data === undefined ? err : err.data} ${err.errObj ? err.errObj.message : '' }` ); } @@ -941,7 +947,7 @@ export class WhatsappDirectLine extends GBService { id = req.from.split('@')[0]; senderName = req._data.notifyName; text = req.body; - + botId = this.botId; break; case 'chatapi': @@ -992,11 +998,14 @@ export class WhatsappDirectLine extends GBService { let urlMin: any = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0]; const botNumber = urlMin ? urlMin.core.getParam(urlMin.instance, 'Bot Number', null) : null; + if (botNumber){ + user = await sec.updateUserInstance(user.userSystemId, urlMin.instance.instanceId); + } let activeMin; // Processes group behaviour. - text = text.replace(/\@\d+ /gi, ''); + text = text.replace(/\@\d+ /gi, ''); let group; if (provider === 'chatapi') { @@ -1120,15 +1129,25 @@ export class WhatsappDirectLine extends GBService { res.end(); } } else { + let t; activeMin = GBServer.globals.minInstances.filter(p => p.instance.instanceId === user.instanceId)[0]; if (activeMin === undefined) { activeMin = GBServer.globals.minBoot; - await (activeMin as any).whatsAppDirectLine.sendToDevice( + t = (activeMin as any).whatsAppDirectLine; + await t.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); + else { + if ((activeMin as any).whatsAppDirectLine) { + t = (activeMin as any).whatsAppDirectLine; + } else { + t = (GBServer.globals.minBoot as any).whatsAppDirectLine; + } + } + + t.received(req, res); } } } else {