From db7ed36707e567fa6801c748d4a28ebca76549c4 Mon Sep 17 00:00:00 2001 From: rodrigorodriguez Date: Sat, 1 Apr 2023 10:42:44 -0300 Subject: [PATCH] fix(core.gbapp): #344 fix regarding SET FILTER keyword. --- .../basic.gblib/services/DialogKeywords.ts | 46 +++++++++++-------- packages/basic.gblib/services/GBVMService.ts | 5 +- .../services/KeywordsExpressions.ts | 7 +++ .../basic.gblib/services/SystemKeywords.ts | 40 ++++++++++------ .../services/WebAutomationServices.ts | 7 ++- 5 files changed, 66 insertions(+), 39 deletions(-) diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index 45a5ac4d..0dbf1a15 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -46,7 +46,7 @@ import { Messages } from '../strings.js'; import * as Fs from 'fs'; import { CollectionUtil } from 'pragmatismo-io-framework'; import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js'; -import phoneUtil from 'google-libphonenumber'; +import phoneUtil from 'google-libphonenumber'; import phone from 'phone'; import DateDiff from 'date-diff'; import tesseract from 'node-tesseract-ocr'; @@ -536,7 +536,7 @@ export class DialogKeywords { this['id'] = new SystemKeywords().getRandomId(); } - private isUserSystemParam(name: string): Boolean { + public static isUserSystemParam(name: string): Boolean { const names = [ 'welcomed', 'loaded', @@ -553,7 +553,7 @@ export class DialogKeywords { return names.indexOf(name) > -1; } - private async setOption({ pid, name, value }) { + public static 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.`); // } @@ -564,7 +564,7 @@ export class DialogKeywords { return { min, user, params }; } - private async getOption({ pid, name }) { + public static async getOption({ pid, name }) { if (this.isUserSystemParam(name)) { throw new Error(`Not possible to retrieve ${name} system param.`); } @@ -580,7 +580,7 @@ export class DialogKeywords { * */ public async setMaxLines({ pid, count }) { - await this.setOption({ pid, name: 'maxLines', value: count }); + await DialogKeywords.setOption({ pid, name: 'maxLines', value: count }); } /** @@ -590,7 +590,7 @@ export class DialogKeywords { * */ public async setUserParam({ pid, name, value }) { - await this.setOption({ pid, name, value }); + await DialogKeywords.setOption({ pid, name, value }); } /** @@ -600,7 +600,7 @@ export class DialogKeywords { * */ public async getUserParam({ pid, name }) { - await this.getOption({ pid, name }); + await DialogKeywords.getOption({ pid, name }); } /** @@ -610,7 +610,18 @@ export class DialogKeywords { * */ public async setMaxColumns({ pid, count }) { - await this.setOption({ pid, name: 'setMaxColumns', value: count }); + await DialogKeywords.setOption({ pid, name: 'setMaxColumns', value: count }); + } + + /** + * Defines a custom user filter for SET calls. + * + * @example SET FILTER "ColumnName=33" + * SET "file.xlsx", "C", "200000" + * + */ + public async setFilter({ pid, value }) { + await DialogKeywords.setOption({ pid, name: 'filter', value }); } /** @@ -621,7 +632,7 @@ export class DialogKeywords { */ public async setWholeWord({ pid, on }) { const value = on.trim() === 'on'; - await this.setOption({ pid, name: 'wholeWord', value: value }); + await DialogKeywords.setOption({ pid, name: 'wholeWord', value: value }); } /** @@ -632,7 +643,7 @@ export class DialogKeywords { */ public async setFilterTypes({ pid, types }) { const value = types; - await this.setOption({ pid, name: 'filterTypes', value: value }); + await DialogKeywords.setOption({ pid, name: 'filterTypes', value: value }); } /** @@ -643,7 +654,7 @@ export class DialogKeywords { */ public async setTheme({ pid, theme }) { const value = theme.trim(); - await this.setOption({ pid, name: 'theme', value: value }); + await DialogKeywords.setOption({ pid, name: 'theme', value: value }); } /** @@ -654,7 +665,7 @@ export class DialogKeywords { */ public async setTranslatorOn({ pid, on }) { const value = on.trim() === 'on'; - await this.setOption({ pid, name: 'translatorOn', value: value }); + await DialogKeywords.setOption({ pid, name: 'translatorOn', value: value }); } /** @@ -1130,13 +1141,9 @@ export class DialogKeywords { url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', Path.basename(localName)); GBLog.info(`BASIC: WebAutomation: Sending the file ${url} to mobile ${mobile}.`); - - } - - else if (filename.url) - { + } else if (filename.url) { url = filename.url; - } + } // Handles Markdown. else if (filename.indexOf('.md') > -1) { @@ -1159,7 +1166,7 @@ export class DialogKeywords { } } - if (url){ + if (url) { const reply = { type: ActivityTypes.Message, text: caption }; const imageData = await (await fetch(url)).arrayBuffer(); @@ -1178,7 +1185,6 @@ export class DialogKeywords { await min.conversationalService['sendOnConversation'](min, user, reply); } } - } /** * Generates a new QRCode. diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index eb915057..20a78a61 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -268,6 +268,8 @@ export class GBVMService extends GBService { let today = this.today; let now = this.now; + // Transfers NLP auto variables into global object. + for(i in this.variables) { global[i] = this.variables[i]; } @@ -286,10 +288,9 @@ export class GBVMService extends GBService { ${code} - await wa.getCloseHandles({pid: pid}); + await wa.closeHandles({pid: pid}); })(); - `; Fs.writeFileSync(jsfile, code); GBLogEx.info(min, `[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${code}`); diff --git a/packages/basic.gblib/services/KeywordsExpressions.ts b/packages/basic.gblib/services/KeywordsExpressions.ts index ed4a2d22..3985ba58 100644 --- a/packages/basic.gblib/services/KeywordsExpressions.ts +++ b/packages/basic.gblib/services/KeywordsExpressions.ts @@ -432,6 +432,13 @@ export class KeywordsExpressions { } ]; + keywords[i++] = [ + /^\s*(set filter)(\s*)(.*)/gim, + ($0, $1, $2, $3) => { + return `await dk.setFilter ({pid: pid, ${$3}})`; + } + ]; + keywords[i++] = [ /^\s*set param \s*(.*)\s*as\s*(.*)/gim, ($0, $1, $2) => { diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index 40f7e679..1e8719d2 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -483,6 +483,16 @@ export class SystemKeywords { return; } + // TODO: Add a semaphore between FILTER and SET. + + // Processes FILTER option to ensure parallel SET calls. + + const filter = await DialogKeywords.getOption({ pid, name }); + if (filter) { + const row = this.find({ pid, handle: null, args: [filter] }); + address += row['line']; + } + // Handles calls for BASIC persistence on sheet files. GBLog.info(`BASIC: Defining '${address}' in '${file}' to '${value}' (SET). `); @@ -536,7 +546,7 @@ export class SystemKeywords { GBLog.info(`BASIC: Saving '${file}' (SAVE file).`); let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min); const botId = min.instance.botId; - const path = DialogKeywords.getGBAIPath(min.botId,`gbdrive`); + const path = DialogKeywords.getGBAIPath(min.botId, `gbdrive`); // Checks if it is a GB FILE object. @@ -563,7 +573,7 @@ export class SystemKeywords { * @exaple SAVE "customers.xlsx", name, email, phone, address, city, state, country * */ - public async save({ pid,file, args }): Promise { + public async save({ pid, file, args }): Promise { const { min, user } = await DialogKeywords.getProcessInfo(pid); args.shift(); GBLog.info(`BASIC: Saving '${file}' (SAVE). Args: ${args.join(',')}.`); @@ -589,7 +599,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 && await this.isValidDate({pid, dt:value})) { + if (value && (await this.isValidDate({ pid, dt: value }))) { value = `'${value}`; } body.values[0][index] = value; @@ -622,7 +632,8 @@ export class SystemKeywords { } else { GBLog.info(`BASIC: GET '${addressOrHeaders}' in '${file}'.`); let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min); - const botId = min.instance.botId;'' + const botId = min.instance.botId; + (''); const path = DialogKeywords.getGBAIPath(botId, 'gbdata'); let document = await this.internalGetDocument(client, baseUrl, path, file); @@ -689,7 +700,7 @@ export class SystemKeywords { * @see NPM package data-forge * */ - public async find({ pid, handle, args }): Promise { + public async find({ pid, handle, args }): Promise { const { min, user, params } = await DialogKeywords.getProcessInfo(pid); const file = args[0]; args.shift(); @@ -714,11 +725,11 @@ export class SystemKeywords { let results; let header, rows; let page; - if (handle){ + if (handle) { page = WebAutomationServices.getPageByHandle(handle); } - if (handle &&page['$eval'] && WebAutomationServices.isSelector(file)) { + if (handle && page['$eval'] && WebAutomationServices.isSelector(file)) { const container = page['frame'] ? page['frame'] : page; const originalSelector = file; @@ -857,10 +868,10 @@ export class SystemKeywords { if (this.isValidHour(filter.value)) { filter.dataType = fixed ? fixed : 'hourInterval'; - } else if (await this.isValidDate({pid, dt: 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 (await this.isValidNumber({pid, number: filter.value})) { + } else if (await this.isValidNumber({ pid, number: filter.value })) { filter.value = Number.parseInt(filter.value); filter.dataType = fixed ? fixed : 'number'; } else { @@ -1003,7 +1014,7 @@ export class SystemKeywords { const propertyName = header[colIndex]; let value = xlRow[colIndex]; if (value && value.charAt(0) === "'") { - if (await this.isValidDate({pid, dt:value.substr(1)})) { + if (await this.isValidDate({ pid, dt: value.substr(1) })) { value = value.substr(1); } } @@ -1103,7 +1114,6 @@ export class SystemKeywords { const botId = min.instance.botId; let path = DialogKeywords.getGBAIPath(min.botId, `gbdrive`); - // Extracts each part of path to call create folder to each // one of them. @@ -1151,7 +1161,7 @@ export class SystemKeywords { public async shareFolder({ pid, folder, email, message }) { const { min, user, params } = await DialogKeywords.getProcessInfo(pid); let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min); - const path = DialogKeywords.getGBAIPath(min.botId,`gbdrive`); + const path = DialogKeywords.getGBAIPath(min.botId, `gbdrive`); const root = urlJoin(path, folder); const src = await client.api(`${baseUrl}/drive/root:/${root}`).get(); @@ -1250,7 +1260,7 @@ export class SystemKeywords { dest = dest.replace(/\\/gi, '/'); // Determines full path at source and destination. - const path = DialogKeywords.getGBAIPath(min.botId,`gbdrive`); + const path = DialogKeywords.getGBAIPath(min.botId, `gbdrive`); const root = path; const srcPath = urlJoin(root, src); const dstPath = urlJoin(path, dest); @@ -1650,7 +1660,7 @@ export class SystemKeywords { const propertyName = header[colIndex]; let value = xlRow[colIndex]; if (value && value.charAt(0) === "'") { - if (await this.isValidDate({pid, dt:value.substr(1)})) { + if (await this.isValidDate({ pid, dt: value.substr(1) })) { value = value.substr(1); } } @@ -1708,7 +1718,7 @@ export class SystemKeywords { args.push(row[keys[j]]); } - await this.save({ pid,file, args }); + await this.save({ pid, file, args }); adds++; } } diff --git a/packages/basic.gblib/services/WebAutomationServices.ts b/packages/basic.gblib/services/WebAutomationServices.ts index 0a525dfe..43cc24bd 100644 --- a/packages/basic.gblib/services/WebAutomationServices.ts +++ b/packages/basic.gblib/services/WebAutomationServices.ts @@ -72,9 +72,12 @@ export class WebAutomationServices { return 4294967296 * (2097151 & h2) + (h1 >>> 0); }; - - public async getCloseHandles({ pid }) { + + public async closeHandles({ pid }) { const { min, user } = await DialogKeywords.getProcessInfo(pid); + + await DialogKeywords.setOption({ pid, name: "filter", value: null }); + // Releases previous allocated OPEN semaphores. let keys = Object.keys(GBServer.globals.webSessions);