new(all): Vm isolated working with IPC BASIC 3.0;

This commit is contained in:
rodrigorodriguez 2022-11-02 19:40:59 -03:00
parent 45f4a48f88
commit 4bbd384501
5 changed files with 335 additions and 320 deletions

View file

@ -2,7 +2,7 @@
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
@ -10,8 +10,8 @@
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| According to our dual licensing model,this program can be used either |
| under the terms of the GNU Affero General Public License,version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
@ -19,13 +19,13 @@
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| but WITHOUT ANY WARRANTY,without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| trademark license. Therefore any rights,title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
@ -99,7 +99,7 @@ export class DialogKeywords {
lastDebugWeb: Date;
/**
* SYSTEM account maxLines, when used with impersonated contexts (eg. running in SET SCHEDULE).
* SYSTEM account maxLines,when used with impersonated contexts (eg. running in SET SCHEDULE).
*/
maxLines: number = 2000;
@ -112,7 +112,7 @@ export class DialogKeywords {
}
/**
* When creating this keyword facade, a bot instance is
* When creating this keyword facade,a bot instance is
* specified among the deployer service.
*/
constructor(min: GBMinInstance, deployer: GBDeployer, user) {
@ -129,7 +129,7 @@ export class DialogKeywords {
}
/**
* Base reference of system keyword facade, called directly
* Base reference of system keyword facade,called directly
* by the script.
*/
public sys(): SystemKeywords {
@ -141,7 +141,7 @@ export class DialogKeywords {
*
* @example x = GET PAGE
*/
public async getPage(url, username, password) {
public async getPage({url, username, password}) {
GBLog.info(`BASIC: Web Automation GET PAGE ${url}.`);
if (!this.browser) {
this.browser = await createBrowser(null);
@ -157,9 +157,9 @@ export class DialogKeywords {
/**
*
*
* Data = [10, 20, 30]
* Data = [10,20,30]
* Legends = "Steve;Yui;Carlos"
* img = CHART "pie", data, legends
* img = CHART "pie",data,legends
*
* https://c3js.org/examples.html
*
@ -167,7 +167,7 @@ export class DialogKeywords {
* @param legends
* @see https://www.npmjs.com/package/plot
*/
public async chart(type, data, legends, transpose) {
public async chart({type, data, legends, transpose}) {
let table = [[]];
@ -177,8 +177,8 @@ export class DialogKeywords {
// Columns and data are merged like:
// columns: [
// ['data1', 30, 200, 100, 400, 150, 250],
// ['data2', 50, 20, 10, 40, 15, 25]
// ['data1',30,200,100,400,150,250],
// ['data2',50,20,10,40,15,25]
// ]
for (let i = 0; i < legends_.length; i++) {
@ -246,18 +246,18 @@ export class DialogKeywords {
/**
* Find element on page DOM.
*
* @example GET page, "elementName"
* @example GET page,"selector"
*/
public async getBySelector(page, elementName) {
GBLog.info(`BASIC: Web Automation GET element: ${elementName}.`);
await page.waitForSelector(elementName)
let elements = await page.$$(elementName);
public async getBySelector({page, selector}) {
GBLog.info(`BASIC: Web Automation GET element: ${selector}.`);
await page.waitForSelector(selector)
let elements = await page.$$(selector);
if (elements && elements.length > 1) {
return elements;
}
else {
const el = elements[0];
el['originalSelector'] = elementName;
el['originalSelector'] = selector;
el['href'] = await page.evaluate(e => e.getAttribute('href'), el);
el['value'] = await page.evaluate(e => e.getAttribute('value'), el);
el['name'] = await page.evaluate(e => e.getAttribute('name'), el);
@ -269,9 +269,9 @@ export class DialogKeywords {
/**
* Find element on page DOM.
*
* @example GET page, "frameSelector, "elementSelector"
* @example GET page,"frameSelector,"elementSelector"
*/
public async getByFrame(page, frame, selector) {
public async getByFrame({page, frame, selector}) {
GBLog.info(`BASIC: Web Automation GET element by frame: ${selector}.`);
await page.waitForSelector(frame)
let frameHandle = await page.$(frame);
@ -290,19 +290,19 @@ export class DialogKeywords {
/**
* Simulates a mouse hover an web page element.
*/
public async hover(page, idOrName) {
GBLog.info(`BASIC: Web Automation HOVER element: ${idOrName}.`);
await this.getBySelector(page, idOrName);
await page.hover(idOrName);
public async hover({page, selector}) {
GBLog.info(`BASIC: Web Automation HOVER element: ${selector}.`);
await this.getBySelector({page, selector: selector});
await page.hover(selector);
await this.debugStepWeb(page);
}
/**
* Clicks on an element in a web page.
*
* @example CLICK page, "#idElement"
* @example CLICK page,"#idElement"
*/
public async click(page, frameOrSelector, selector) {
public async click({page, frameOrSelector, selector}) {
GBLog.info(`BASIC: Web Automation CLICK element: ${frameOrSelector}.`);
if (selector) {
await page.waitForSelector(frameOrSelector)
@ -326,20 +326,21 @@ export class DialogKeywords {
}
if (this.debugWeb && refresh) {
const adminNumber = this.min.core.getParam(this.min.instance, 'Bot Admin Number', null);
if (adminNumber) {
await this.sendFileTo(adminNumber, page, "General Bots Debugger");
const mobile = this.min.core.getParam(this.min.instance, 'Bot Admin Number', null);
const filename = page;
if (mobile) {
await this.sendFileTo({mobile , filename, caption:"General Bots Debugger"});
}
this.lastDebugWeb = new Date();
}
}
/**
* Press ENTER in a web page, useful for logins.
* Press ENTER in a web page,useful for logins.
*
* @example PRESS ENTER ON page
*/
public async pressKey(page, char, frame) {
public async pressKey({page, char, frame}) {
GBLog.info(`BASIC: Web Automation PRESS ${char} ON element: ${frame}.`);
if (char.toLowerCase() === "enter") {
char = '\n';
@ -355,12 +356,12 @@ export class DialogKeywords {
}
}
public async linkByText(page, text, index) {
public async linkByText({page, text, index}) {
GBLog.info(`BASIC: Web Automation CLICK LINK TEXT: ${text} ${index}.`);
if (!index) {
index = 1
}
const els = await page.$x(`//a[contains(., '${text}')]`);
const els = await page.$x(`//a[contains(.,'${text}')]`);
await els[index - 1].click();
await this.debugStepWeb(page);
}
@ -372,8 +373,8 @@ export class DialogKeywords {
*
* @example file = SCREENSHOT page
*/
public async screenshot(page, idOrName) {
GBLog.info(`BASIC: Web Automation SCREENSHOT ${idOrName}.`);
public async screenshot({page, selector}) {
GBLog.info(`BASIC: Web Automation SCREENSHOT ${selector}.`);
const gbaiName = `${this.min.botId}.gbai`;
const localName = Path.join('work', gbaiName, 'cache', `screen-${GBAdminService.getRndReadableIdentifier()}.jpg`);
@ -395,11 +396,11 @@ export class DialogKeywords {
/**
* Types the text into the text field.
*
* @example SET page, "elementName", "text"
* @example SET page,"selector","text"
*/
public async setElementText(page, idOrName, text) {
GBLog.info(`BASIC: Web Automation TYPE on ${idOrName}: ${text}.`);
const e = await this.getBySelector(page, idOrName);
public async setElementText({page, selector, text}) {
GBLog.info(`BASIC: Web Automation TYPE on ${selector}: ${text}.`);
const e = await this.getBySelector({page, selector});
await e.click({ clickCount: 3 });
await page.keyboard.press('Backspace');
await e.type(text, { delay: 200 });
@ -410,7 +411,7 @@ export class DialogKeywords {
* Returns the OCR of image file.
*
*/
public async getOCR(localFile) {
public async getOCR({localFile}) {
GBLog.info(`BASIC: OCR processing on ${localFile}.`);
const tesseract = require("node-tesseract-ocr")
@ -428,7 +429,7 @@ export class DialogKeywords {
*
* @example x = TODAY
*/
public async getToday() {
public async getToday({}) {
let d = new Date(),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
@ -456,11 +457,11 @@ export class DialogKeywords {
}
/**
* Quits the dialog, currently required to get out of VM context.
* Quits the dialog,currently required to get out of VM context.
*
* @example EXIT
*/
public async exit() {
public async exit({}) {
}
@ -469,7 +470,7 @@ export class DialogKeywords {
*
* @example list = ACTIVE TASKS
*/
public async getActiveTasks() {
public async getActiveTasks({}) {
let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY);
return await s.getActiveTasks();
}
@ -477,9 +478,9 @@ export class DialogKeywords {
/**
* Creates a new deal.
*
* @example CREATE DEAL dealname, contato, empresa, amount
* @example CREATE DEAL dealname,contato,empresa,amount
*/
public async createDeal(dealName, contact, company, 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;
@ -490,7 +491,7 @@ export class DialogKeywords {
*
* @example list = FIND CONTACT "Sandra"
*/
public async fndContact(name) {
public async fndContact({name}) {
let s = new HubSpotServices(null, null, process.env.HUBSPOT_KEY);
return await s.searchContact(name);
}
@ -510,7 +511,7 @@ export class DialogKeywords {
}
public async getCoded(value) {
public async getCoded({value}) {
// Checks if it is a GB FILE object.
@ -552,9 +553,9 @@ export class DialogKeywords {
/**
* Returns an object ready to get information about difference in several ways
* like years, months or days.
* like years,months or days.
*
* @example days = DATEDIFF date1, date2, mode
* @example days = DATEDIFF date1,date2,mode
*
*/
public dateDiff(date1, date2, mode) {
@ -580,7 +581,7 @@ export class DialogKeywords {
/**
* Returns specified date week day in format 'Mon'.
*
* @example DATEADD date, "minute", 60
* @example DATEADD date,"minute",60
*
* https://stackoverflow.com/a/1214753/18511
*/
@ -610,7 +611,7 @@ export class DialogKeywords {
/**
* Returns specified list member separated by comma.
*
* @example TALK TOLIST (array, member)
* @example TALK TOLIST (array,member)
*
*/
public getToLst(array, member) {
@ -623,7 +624,7 @@ export class DialogKeywords {
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(", ");
array = array.join(",");
return array;
}
@ -662,10 +663,10 @@ export class DialogKeywords {
/**
* Returns current time in format hh:dd.
*
* @example SAVE "file.xlsx", name, email, NOW
* @example SAVE "file.xlsx",name,email,NOW
*
*/
public async getNow() {
public async getNow({}) {
const contentLocale = this.min.core.getParam<string>(
this.min.instance,
'Default Content Language',
@ -689,14 +690,14 @@ export class DialogKeywords {
*
* @example
*
* SEND MAIL "email@domain.com", "Subject", "Message text."
* SEND MAIL "email@domain.com","Subject", "Message text."
*
*/
public async sendEmail(to, subject, body) {
public async sendEmail({to, subject, body}) {
// tslint:disable-next-line:no-console
GBLog.info(`[E-mail]: to:${to}, subject: ${subject}, body: ${body}.`);
GBLog.info(`[E-mail]: to:${to},subject: ${subject},body: ${body}.`);
const emailToken = process.env.EMAIL_API_KEY;
// Inline word document used as e-mail body.
@ -729,12 +730,12 @@ export class DialogKeywords {
/**
* Sends a file to a given mobile.
*
* @example SEND FILE TO "+199988887777", "image.jpg", caption
* @example SEND FILE TO "+199988887777","image.jpg",caption
*
*/
public async sendFileTo(mobile, filename, caption) {
GBLog.info(`BASIC: SEND FILE TO '${mobile}', filename '${filename}'.`);
return await this.internalSendFile(mobile, filename, caption);
public async sendFileTo({mobile, filename, caption}) {
GBLog.info(`BASIC: SEND FILE TO '${mobile}',filename '${filename}'.`);
return await this.internalSendFile({mobile, filename, caption});
}
/**
@ -743,10 +744,10 @@ export class DialogKeywords {
* @example SEND FILE "image.jpg"
*
*/
public async sendFile(filename, caption) {
public async sendFile({filename, caption}) {
const mobile = await this.userMobile();
GBLog.info(`BASIC: SEND FILE (current: ${mobile}, filename '${filename}'.`);
return await this.internalSendFile(mobile, filename, caption);
GBLog.info(`BASIC: SEND FILE (current: ${mobile},filename '${filename}'.`);
return await this.internalSendFile({mobile, filename, caption});
}
/**
@ -755,7 +756,7 @@ export class DialogKeywords {
* @example SET LANGUAGE "pt"
*
*/
public async setLanguage(language) {
public async setLanguage({language}) {
const sec = new SecService();
await sec.updateUserLocale(this.user.userId, language);
}
@ -766,7 +767,7 @@ export class DialogKeywords {
* @example SET ID NUMBER
*
*/
public async setIdGeneration(mode) {
public async setIdGeneration({mode}) {
this['idGeneration'] = mode;
this['id'] = await this.sys().getRandomId();
}
@ -777,7 +778,7 @@ export class DialogKeywords {
* @example SET MAX LINES 5000
*
*/
public async setMaxLines(count) {
public async setMaxLines({count}) {
if (this.user) {
// TODO: PARAM user.basicOptions.maxLines = count;
}
@ -793,7 +794,7 @@ export class DialogKeywords {
* @example SET MAX COLUMNS 5000
*
*/
public async setMaxColumns(count) {
public async setMaxColumns({count}) {
// TODO: user.basicOptions.maxColumns = count;
}
@ -805,7 +806,7 @@ export class DialogKeywords {
* @example SET WHOLE WORD ON
*
*/
public async setWholeWord(on) {
public async setWholeWord({on}) {
// TODO: user.basicOptions.wholeWord = (on.trim() === "on");
}
@ -815,7 +816,7 @@ export class DialogKeywords {
* @example SET THEME "themename"
*
*/
public async setTheme(theme) {
public async setTheme({theme}) {
// TODO: user.basicOptions.theme = theme.trim();
}
@ -825,7 +826,7 @@ export class DialogKeywords {
* @example SET TRANSLATOR ON | OFF
*
*/
public async setTranslatorOn(on) {
public async setTranslatorOn({on}) {
// TODO: user.basicOptions.translatorOn = (on.trim() === "on");
}
@ -853,14 +854,14 @@ export class DialogKeywords {
* @example MENU
*
*/
public async showMenu() {
public async showMenu({}) {
// TODO: return await beginDialog('/menu');
}
private static async downloadAttachmentAndWrite(attachment) {
const url = attachment.contentUrl;
const localFolder = Path.join('work'); // TODO: , '${botId}', 'uploads');
const localFolder = Path.join('work'); // TODO: ,'${botId}','uploads');
const localFileName = Path.join(localFolder, attachment.name);
try {
@ -892,7 +893,7 @@ export class DialogKeywords {
console.error(error);
return undefined;
}
// If no error was thrown while writing to disk, return the attachment's name
// If no error was thrown while writing to disk,return the attachment's name
// and localFilePath for the response back to the user.
return {
fileName: attachment.name,
@ -906,8 +907,8 @@ export class DialogKeywords {
* @example TRANSFER
*
*/
public async transferTo(to: string = null) {
// TODO: return await beginDialog('/t', { to: to });
public async transferTo({to}) {
// TODO: return await beginDialog('/t',{ to: to });
}
/**
@ -916,7 +917,15 @@ export class DialogKeywords {
* @example HEAR name
*
*/
public async hear(kind, ...args) {
public async getHear({kind, arg}) {
// Handles first arg as an array of args.
let args = [];
if (arg && arg.length) {
args = arg;
}
try {
@ -942,15 +951,16 @@ export class DialogKeywords {
let choices = [];
let i = 0;
args.forEach(arg => {
await CollectionUtil.asyncForEach(args, async arg => {
i++;
choices.push({ body: arg, id: `button${i}` });
// DISABLED: choices.push({ body: arg, id: `button${i}` });
await this.talk(arg);
});
const button = new Buttons(Messages[locale].choices, choices, ' ', ' ');
// DISABLED const button = new Buttons(Messages[locale].choices, choices, ' ', ' ');
// await this.talk(button);
await this.talk(button);
GBLog.info(`BASIC: HEAR with ${args.toString()} (Asking for input).`);
GBLog.info(`BASIC: HEAR with [${args.toString()}] (Asking for input).`);
}
else {
@ -974,7 +984,7 @@ export class DialogKeywords {
const text = this.min.cbMap[userId].promise;
if (kind === "file") {
// await prompt('attachmentPrompt', {});
// await prompt('attachmentPrompt',{});
// // Prepare Promises to download each attachment and then execute each Promise.
// const promises = step.context.activity.attachments.map(
@ -983,11 +993,11 @@ export class DialogKeywords {
// async function replyForReceivedAttachments(localAttachmentData) {
// if (localAttachmentData) {
// // Because the TurnContext was bound to this function, the bot can call
// // Because the TurnContext was bound to this function,the bot can call
// // `TurnContext.sendActivity` via `this.sendActivity`;
// await this.sendActivity(`Upload OK.`);
// } else {
// await this.sendActivity('Error uploading file. Please, start again.');
// await this.sendActivity('Error uploading file. Please,start again.');
// }
// }
@ -1019,8 +1029,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null) {
await this.talk("Por favor, digite um e-mail válido.");
return await this.hear(kind, args);
await this.talk({text: "Por favor,digite um e-mail válido."});
return await this.getHear({kind, arg});
}
result = value;
@ -1034,8 +1044,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null || value.length != 1) {
await this.talk("Por favor, digite um nome válido.");
return await this.hear(kind, args);
await this.talk({text:"Por favor,digite um nome válido."});
return await this.getHear({kind, arg});
}
result = value;
@ -1049,8 +1059,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null || value.length != 1) {
await this.talk("Por favor, digite um número válido.");
return await this.hear(kind, args);
await this.talk({text:"Por favor,digite um número válido."});
return await this.getHear({kind, arg});
}
result = value;
@ -1063,8 +1073,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null || value.length != 1) {
await this.talk("Por favor, digite uma data no formato 12/12/2020.");
return await this.hear(kind, args);
await this.talk({text:"Por favor,digite uma data no formato 12/12/2020."});
return await this.getHear({kind, arg});
}
result = value;
@ -1078,8 +1088,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null || value.length != 1) {
await this.talk("Por favor, digite um horário no formato hh:ss.");
return await this.hear(kind, args);
await this.talk({text:"Por favor,digite um horário no formato hh:ss."});
return await this.getHear({kind, arg});
}
result = value;
@ -1099,8 +1109,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null || value.length != 1) {
await this.talk("Por favor, digite um valor monetário.");
return await this.hear(kind, args);
await this.talk({text:"Por favor,digite um valor monetário."});
return await this.getHear({kind, arg});
}
result = value;
@ -1114,11 +1124,11 @@ export class DialogKeywords {
} catch (error) {
await this.talk(Messages[locale].validation_enter_valid_mobile);
return await this.hear(kind, args);
return await this.getHear({kind, arg});
}
if (!phoneUtil.isPossibleNumber(phoneNumber)) {
await this.talk("Por favor, digite um número de telefone válido.");
return await this.hear(kind, args);
await this.talk({text:"Por favor,digite um número de telefone válido."});
return await this.getHear({kind, arg});
}
result = phoneNumber;
@ -1141,8 +1151,8 @@ export class DialogKeywords {
const value = extractEntity(text);
if (value === null || value.length != 1) {
await this.talk("Por favor, digite um valor monetário.");
return await this.hear(kind, args);
await this.talk({text:"Por favor, digite um CEP válido."});
return await this.getHear({kind, arg});
}
result = value[0];
@ -1159,8 +1169,8 @@ export class DialogKeywords {
});
if (result === null) {
await this.talk(`Escolha por favor um dos itens sugeridos.`);
return await this.hear(kind, args);
await this.talk({text:`Escolha por favor um dos itens sugeridos.`});
return await this.getHear({kind, arg});
}
}
else if (kind === "language") {
@ -1184,8 +1194,6 @@ export class DialogKeywords {
];
// TODO: const text = step.context.activity['originalText'];
await CollectionUtil.asyncForEach(list, async item => {
if (GBConversationalService.kmpSearch(text.toLowerCase(), item.name.toLowerCase()) != -1 ||
GBConversationalService.kmpSearch(text.toLowerCase(), item.code.toLowerCase()) != -1) {
@ -1194,9 +1202,8 @@ export class DialogKeywords {
});
if (result === null) {
// TODO:
await this.min.conversationalService.sendText(this.min, null, `Escolha por favor um dos idiomas sugeridos.`);
return await this.hear(kind, args);
await this.talk({text:`Escolha por favor um dos itens sugeridos.`});
return await this.getHear({kind, arg});
}
}
return result;
@ -1208,7 +1215,7 @@ export class DialogKeywords {
/**
* Prepares the next dialog to be shown to the specified user.
*/
public async gotoDialog(fromOrDialogName: string, dialogName: string) {
public async gotoDialog({fromOrDialogName, dialogName}) {
if (dialogName) {
if (dialogName.charAt(0) === '/') {
// TODO: await step.beginDialog(fromOrDialogName);
@ -1227,7 +1234,7 @@ export class DialogKeywords {
}
}
public async getSingleton() {
public async getSingleton({}) {
return {
id: this.sys().getRandomId(),
username: this.userName(),
@ -1245,7 +1252,7 @@ export class DialogKeywords {
/**
* Talks to the user by using the specified text.
*/
public async talk(text: string) {
public async talk({text}) {
GBLog.info(`BASIC: TALK '${text}'.`);
if (this.user) {
const translate = this.user ? this.user.basicOptions.translatorOn : false;
@ -1264,9 +1271,9 @@ export class DialogKeywords {
/**
* Processes the sending of the file.
*/
private async internalSendFile(mobile, filename, caption) {
private async internalSendFile({mobile, filename, caption}) {
// Handles SEND FILE TO mobile, element in Web Automation.
// Handles SEND FILE TO mobile,element in Web Automation.
const element = filename._page ? filename._page : (filename.screenshot ? filename : null);
@ -1319,7 +1326,7 @@ export class DialogKeywords {
}
}
public async getQRCode(text) {
public async getQRCode({text}) {
const img = await qrcode.toDataURL(text);
const data = img.replace(/^data:image\/\w+;base64,/, "");
const buf = Buffer.from(data, "base64");

View file

@ -161,6 +161,124 @@ export class GBVMService extends GBService {
});
}
public async translateBASIC(filename: any, min: GBMinInstance, deployer: GBDeployer, mainName: string) {
// Converts General Bots BASIC into regular VBS
let basicCode: string = fs.readFileSync(filename, 'utf8');
// Processes END keyword, removing extracode, useful
// for development.
let end = /(\nend\n)/gi.exec(basicCode);
if (end) {
basicCode = basicCode.substring(0, end.index);
}
// Removes comments.
basicCode = basicCode.replace(/((^|\W)REM.*\n)/gi, '');
// Process INCLUDE keyword to include another
// dialog inside the dialog.
let include = null;
do {
include = /^include\b(.*)$/gmi.exec(basicCode);
if (include) {
let includeName = include[1].trim();
includeName = Path.join(Path.dirname(filename), includeName);
includeName = includeName.substr(0, includeName.lastIndexOf(".")) + ".vbs";
// To use include, two /publish will be necessary (for now)
// because of alphabet order may raise not found errors.
let includeCode: string = fs.readFileSync(includeName, 'utf8');
basicCode = basicCode.replace(/^include\b.*$/gmi, includeCode);
}
} while (include);
const vbsCode = this.convertGBASICToVBS(min, basicCode);
const vbsFile = `${filename}.compiled`;
fs.writeFileSync(vbsFile, vbsCode);
// Converts VBS into TS.
vb2ts.convertFile(vbsFile);
// Convert TS into JS.
const tsfile: string = `${filename}.ts`;
let tsCode: string = fs.readFileSync(tsfile, 'utf8');
fs.writeFileSync(tsfile, tsCode);
const tsc = new TSCompiler();
tsc.compile([tsfile]);
// Run JS into the GB context.
const jsfile = `${tsfile}.js`.replace('.ts', '');
if (fs.existsSync(jsfile)) {
let code: string = fs.readFileSync(jsfile, 'utf8');
code = code.replace(/^.*exports.*$/gm, '');
code = `
return (async () => {
require('isomorphic-fetch');
const rest = require ('typescript-rest-rpc/lib/client');
// Interprocess communication from local HTTP to the BotServer.
const dk = rest.createClient('http://localhost:1111/api/v2/${min.botId}/dialog');
const sys = rest.createClient('http://localhost:1111/api/v2/${min.botId}/system');
// Local variables.
const gb = await dk.getSingleton();
const id = gb.id;
const username = gb.username;
const mobile = gb.mobile;
const from = gb.from;
const ENTER = gb.ENTER;
const headers = gb.headers;
const data = gb.data;
const list = gb.list;
const httpUsername = gb.httpUsername;
const httpPs = gb.httpPs;
// Local functions.
const ubound = (array) => {return array.length};
const isarray = (array) => {return Array.isArray(array) };
// Remote functions.
const weekday = (v) => { return (async () => { return await client.getWeekFromDate(v) })(); };
const hour = (v) => { return (async () => { return await client.getHourFromDate(v) })(); };
const base64 = (v) => { return (async () => { return await client.getCoded(v) })(); };
const tolist = (v) => { return (async () => { return await client.getToLst(v) })(); };
const now = (v) => { return (async () => { return await client.getNow(v) })(); };
const today = (v) => { return (async () => { return await client.getToday(v) })(); };
${code}
})();
`;
// Finds all hear calls.
const parsedCode = beautify(code, { indent_size: 2, space_in_empty_paren: true });
fs.writeFileSync(jsfile, parsedCode);
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
GBLog.info(`[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${parsedCode}`);
}
}
public static getMethodNameFromVBSFilename(filename: string) {
let mainName = filename.replace(/\s|\-/gi, '').split('.')[0];
return mainName.toLowerCase();
@ -220,7 +338,7 @@ export class GBVMService extends GBService {
});
code = code.replace(/(\w+)\s*\=\s*get html\s*(.*)/gi, ($0, $1, $2, $3) => {
return `${$1} = await dk.getPage(step, ${$2})\n`;
return `${$1} = await dk.getPage(${$2})\n`;
});
code = code.replace(/(set hear on)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
@ -228,59 +346,59 @@ export class GBVMService extends GBService {
});
code = code.replace(/hear (\w+) as login/gi, ($0, $1) => {
return `${$1} = await dk.hear("login")`;
return `${$1} = await dk.getHear({{"login"})`;
});
code = code.replace(/hear (\w+) as email/gi, ($0, $1) => {
return `${$1} = await dk.hear("email")`;
return `${$1} = await dk.getHear({"email"})`;
});
code = code.replace(/hear (\w+) as integer/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("integer")`;
return `${$1} = await dk.getHear({"integer"})`;
});
code = code.replace(/hear (\w+) as file/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("file")`;
return `${$1} = await dk.getHear({"file"})`;
});
code = code.replace(/hear (\w+) as boolean/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("boolean")`;
return `${$1} = await dk.getHear({"boolean"})`;
});
code = code.replace(/hear (\w+) as name/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("name")`;
return `${$1} = await dk.getHear({"name"})`;
});
code = code.replace(/hear (\w+) as date/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("date")`;
return `${$1} = await dk.getHear({"date"})`;
});
code = code.replace(/hear (\w+) as hour/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("hour")`;
return `${$1} = await dk.getHear({"hour"})`;
});
code = code.replace(/hear (\w+) as phone/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("phone")`;
return `${$1} = await dk.getHear({"phone"})`;
});
code = code.replace(/hear (\w+) as money/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("money")`;
return `${$1} = await dk.getHear({"money")}`;
});
code = code.replace(/hear (\w+) as language/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("language")`;
return `${$1} = await dk.getHear({"language")}`;
});
code = code.replace(/hear (\w+) as zipcode/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("zipcode")`;
return `${$1} = await dk.getHear({"zipcode")}`;
});
code = code.replace(/hear (\w+) as (.*)/gi, ($0, $1, $2) => {
return `${$1} = await dk.hear("menu", ${$2})`;
return `${$1} = await dk.getHear({"menu", [${$2}])}`;
});
code = code.replace(/(hear)\s*(\w+)/gi, ($0, $1, $2) => {
return `${$2} = await dk.hear()`;
return `${$2} = await dk.getHear({})`;
});
code = code.replace(/(\w)\s*\=\s*find contact\s*(.*)/gi, ($0, $1, $2, $3) => {
@ -313,7 +431,7 @@ export class GBVMService extends GBService {
});
code = code.replace(/(\w)\s*\=\s*append\s*(.*)/gi, ($0, $1, $2, $3) => {
return `${$1} = await sys.append(${$2})\n`;
return `${$1} = await sys.append([${$2}])\n`;
});
code = code.replace(/(\w+)\s*\=\s*sort\s*(\w+)\s*by(.*)/gi, ($0, $1, $2, $3) => {
@ -374,11 +492,11 @@ export class GBVMService extends GBService {
code = code.replace(/(go to)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.gotoDialog(step, ${$3})\n`;
return `await dk.gotoDialog(${$3})\n`;
});
code = code.replace(/(set language)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.setLanguage (step, ${$3})\n`;
return `await dk.setLanguage (${$3})\n`;
});
code = code.replace(/set header\s*(.*)\sas\s(.*)/gi, ($0, $1, $2) => {
@ -394,31 +512,31 @@ export class GBVMService extends GBService {
});
code = code.replace(/(datediff)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.dateDiff (step, ${$3})\n`;
return `await dk.dateDiff (${$3})\n`;
});
code = code.replace(/(dateadd)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.dateAdd (step, ${$3})\n`;
return `await dk.dateAdd (${$3})\n`;
});
code = code.replace(/(set max lines)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.setMaxLines (step, ${$3})\n`;
return `await dk.setMaxLines (${$3})\n`;
});
code = code.replace(/(set max columns)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.setMaxColumns (step, ${$3})\n`;
return `await dk.setMaxColumns (${$3})\n`;
});
code = code.replace(/(set translator)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.setTranslatorOn (step, "${$3.toLowerCase()}")\n`;
return `await dk.setTranslatorOn ("${$3.toLowerCase()}")\n`;
});
code = code.replace(/(set theme)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.setTheme (step, "${$3.toLowerCase()}")\n`;
return `await dk.setTheme ("${$3.toLowerCase()}")\n`;
});
code = code.replace(/(set whole word)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.setWholeWord (step, "${$3.toLowerCase()}")\n`;
return `await dk.setWholeWord ("${$3.toLowerCase()}")\n`;
});
code = code.replace(/(\w+)\s*\=\s*post\s*(.*),\s*(.*)/gi, ($0, $1, $2, $3) => {
@ -446,11 +564,11 @@ export class GBVMService extends GBService {
});
code = code.replace(/(chart)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.chart (step, ${$3})\n`;
return `await dk.chart (${$3})\n`;
});
code = code.replace(/(transfer to)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.transferTo (step, ${$3})\n`;
return `await dk.transferTo (${$3})\n`;
});
code = code.replace(/(\btransfer\b)(?=(?:[^"]|"[^"]*")*$)/gi, () => {
@ -470,7 +588,7 @@ export class GBVMService extends GBService {
});
code = code.replace(/(talk)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.talk (step, ${$3})\n`;
return `await dk.talk (${$3})\n`;
});
code = code.replace(/(send sms to)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
@ -486,23 +604,23 @@ export class GBVMService extends GBService {
});
code = code.replace(/(send file to)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.sendFileTo (step, ${$3})\n`;
return `await dk.sendFileTo (${$3})\n`;
});
code = code.replace(/(hover)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.hover (step, ${$3})\n`;
return `await dk.hover (${$3})\n`;
});
code = code.replace(/(click link text)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.linkByText (step, ${$3})\n`;
return `await dk.linkByText (${$3})\n`;
});
code = code.replace(/(click)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.click (step, ${$3})\n`;
return `await dk.click (${$3})\n`;
});
code = code.replace(/(send file)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.sendFile (step, ${$3})\n`;
return `await dk.sendFile (${$3})\n`;
});
code = code.replace(/(copy)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
@ -523,15 +641,15 @@ export class GBVMService extends GBService {
});
code = code.replace(/PRESS\s(.*)\sON\s(.*)/gi, ($0, $1, $2) => {
return `await dk.pressKey(step, ${$2}, ${$1})\n`;
return `await dk.pressKey(${$2}, ${$1})\n`;
});
code = code.replace(/SCREENSHOT\s(.*)/gi, ($0, $1, $2) => {
return `await dk.screenshot(step, ${$1})\n`;
return `await dk.screenshot(${$1})\n`;
});
code = code.replace(/TWEET\s(.*)/gi, ($0, $1, $2) => {
return `await sys.tweet(step, ${$1})\n`;
return `await sys.tweet(${$1})\n`;
});
code = code.replace(/(\w+)\s*\=\s*(.*)\s*as image/gi, ($0, $1, $2) => {
@ -550,7 +668,7 @@ export class GBVMService extends GBService {
return `await sys.saveFile(${$2}, ${$1})\n`;
});
code = code.replace(/(save)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await sys.save(${$3})\n`;
return `await sys.save([${$3}])\n`;
});
code = code.replace(/set\s(.*)/gi, ($0, $1, $2) => {
@ -562,137 +680,17 @@ export class GBVMService extends GBService {
return code;
}
public async translateBASIC(filename: any, min: GBMinInstance, deployer: GBDeployer, mainName: string) {
// Converts General Bots BASIC into regular VBS
let basicCode: string = fs.readFileSync(filename, 'utf8');
// Processes END keyword, removing extracode, useful
// for development.
let end = /(\nend\n)/gi.exec(basicCode);
if (end) {
basicCode = basicCode.substring(0, end.index);
}
// Removes comments.
basicCode = basicCode.replace(/((^|\W)REM.*\n)/gi, '');
// Process INCLUDE keyword to include another
// dialog inside the dialog.
let include = null;
do {
include = /^include\b(.*)$/gmi.exec(basicCode);
if (include) {
let includeName = include[1].trim();
includeName = Path.join(Path.dirname(filename), includeName);
includeName = includeName.substr(0, includeName.lastIndexOf(".")) + ".vbs";
// To use include, two /publish will be necessary (for now)
// because of alphabet order may raise not found errors.
let includeCode: string = fs.readFileSync(includeName, 'utf8');
basicCode = basicCode.replace(/^include\b.*$/gmi, includeCode);
}
} while (include);
const vbsCode = this.convertGBASICToVBS(min, basicCode);
const vbsFile = `${filename}.compiled`;
fs.writeFileSync(vbsFile, vbsCode);
// Converts VBS into TS.
vb2ts.convertFile(vbsFile);
// Convert TS into JS.
const tsfile: string = `${filename}.ts`;
let tsCode: string = fs.readFileSync(tsfile, 'utf8');
tsCode = tsCode + `let resolve;`;
fs.writeFileSync(tsfile, tsCode);
const tsc = new TSCompiler();
tsc.compile([tsfile]);
// Run JS into the GB context.
const jsfile = `${tsfile}.js`.replace('.ts', '');
if (fs.existsSync(jsfile)) {
let code: string = fs.readFileSync(jsfile, 'utf8');
code = code.replace(/^.*exports.*$/gm, '');
code = `
return (async () => {
require('isomorphic-fetch);
const rest = require ('typescript-rest-rpc/lib/client');
// Interprocess communication from local HTTP to the BotServer.
dk = rest.createClient('http://localhost:1111/api/v2/${min.botId}/dialog');
sys = rest.createClient('http://localhost:1111/api/v2/${min.botId}/system');
// Local variables.
gb = dk.getSingleton(url);
const id = gb.id;
const username = gb.username;
const mobile = gb.mobile;
const from = gb.from;
const ENTER = gb.ENTER;
const headers = gb.headers;
const data = gb.data;
const list = gb.list;
const httpUsername = gb.httpUsername;
const httpPs = gb.httpPs;
// Local functions.
const ubound = (array) => {return array.length};
const isarray = (array) => {return Array.isArray(array) };
// Remote functions.
const weekday = (v) => { (async () => { await client.getWeekFromDate(v) })(); };
const hour = (v) => { (async () => { await client.getHourFromDate(v) })(); };
const base64 = (v) => { (async () => { await client.getCoded(v) })(); };
const tolist = (v) => { (async () => { await client.getToLst(v) })(); };
const now = (v) => { (async () => { await client.getNow(v) })(); };
const today = (v) => { (async () => { await client.getToday(v) })(); };
${code}
})();
`;
// Finds all hear calls.
const parsedCode = beautify(code, { indent_size: 2, space_in_empty_paren: true });
fs.writeFileSync(jsfile, parsedCode);
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
GBLog.info(`[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${parsedCode}`);
}
}
/**
* Executes the converted JavaScript from BASIC code inside execution context.
*/
public static async callVM(text: string, min: GBMinInstance, step: GBDialogStep, deployer: GBDeployer) {
public static async callVM(text: string, min: GBMinInstance, step, GBDialogdeployer: GBDeployer) {
// Creates a class DialogKeywords which is the *this* pointer
// in BASIC.
const user = step ? await min.userProfile.get(step.context, {}) : null;
const sandbox = { user: user.ssystemUser };
const sandbox = { user: user.systemUser };
const contentLocale = min.core.getParam<string>(
min.instance,

View file

@ -92,11 +92,17 @@ export class SystemKeywords {
}
public async callVM(text: string, min: GBMinInstance, step, deployer: GBDeployer) {
public async callVM({text}) {
// TODO:
const min = null;
const step = null;
const deployer = null;
return await GBVMService.callVM(text, min, step, deployer);
}
public async append(...args) {
public async append({args}) {
let array = [].concat(...args);
return array.filter(function (item, pos) { return item; });
}
@ -107,7 +113,7 @@ export class SystemKeywords {
* @example SEE CAPTION OF url AS variable
*
*/
public async seeCaption(url) {
public async seeCaption({url}) {
const computerVisionClient = new ComputerVisionClient(
new ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': process.env.VISION_KEY } }),
process.env.VISION_ENDPOINT);
@ -135,7 +141,7 @@ export class SystemKeywords {
* @example SEE TEXT OF url AS variable
*
*/
public async seeText(url) {
public async seeText({url}) {
const computerVisionClient = new ComputerVisionClient(
new ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': process.env.VISION_KEY } }),
process.env.VISION_ENDPOINT);
@ -160,7 +166,7 @@ export class SystemKeywords {
return final;
}
public async sortBy(array, memberName) {
public async sortBy({array, memberName}) {
memberName = memberName.trim();
const contentLocale = this.min.core.getParam<string>(
this.min.instance,
@ -345,18 +351,18 @@ export class SystemKeywords {
return [url, localName];
}
public async asPDF(data, filename) {
public async asPDF({data, filename}) {
let file = await this.renderTable(data, true, false);
return file[0];
}
public async asImage(data, filename) {
public async asImage({data, filename}) {
let file = await this.renderTable(data, false, true);
return file[0];
}
public async executeSQL(data, sql, tableName) {
public async executeSQL({data, sql, tableName}) {
let objectMode = false;
if (Object.keys(data[0])) {
@ -377,7 +383,7 @@ export class SystemKeywords {
/**
* Retrives the content of a given URL.
*/
public async getFileContents(url, headers) {
public async getFileContents({url, headers}) {
const options = {
url: url,
method: 'GET',
@ -405,7 +411,7 @@ export class SystemKeywords {
/**
* Retrives stock inforation for a given symbol.
*/
public async getStock(symbol) {
public async getStock({symbol}) {
var options = {
uri: `http://live-nse.herokuapp.com/?symbol=${symbol}`
};
@ -421,7 +427,7 @@ export class SystemKeywords {
* @example WAIT 5 ' This will wait five seconds.
*
*/
public async wait(seconds: number) {
public async wait({seconds}) {
// tslint:disable-next-line no-string-based-set-timeout
GBLog.info(`BASIC: WAIT for ${seconds} second(s).`);
const timeout = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
@ -434,7 +440,7 @@ export class SystemKeywords {
* @example TALK TO "+199988887777", "Message text here"
*
*/
public async talkTo(mobile: any, message: string) {
public async talkTo({mobile, message}) {
GBLog.info(`BASIC: Talking '${message}' to a specific user (${mobile}) (TALK TO). `);
await this.min.conversationalService.sendMarkdownToMobile(this.min, null, mobile, message);
}
@ -445,7 +451,7 @@ export class SystemKeywords {
* @example SEND SMS TO "+199988887777", "Message text here"
*
*/
public async sendSmsTo(mobile, message) {
public async sendSmsTo({mobile, message}) {
GBLog.info(`BASIC: SEND SMS TO '${mobile}', message '${message}'.`);
await this.min.conversationalService.sendSms(this.min, mobile, message);
}
@ -459,13 +465,14 @@ export class SystemKeywords {
* @example SET page, "elementHTMLSelector", "text"
*
*/
public async set(file: any, address: string, value: any): Promise<any> {
public async set({file, address, value}): Promise<any> {
// Handles calls for HTML stuff
if (file._javascriptEnabled) {
GBLog.info(`BASIC: Web automation setting ${file}' to '${value}' (SET). `);
await this.dk.setElementText(file, address, value);
const page = file;
GBLog.info(`BASIC: Web automation setting ${page}' to '${value}' (SET). `);
await this.dk.setElementText({page, selector: address, text: value});
return;
}
@ -520,7 +527,7 @@ export class SystemKeywords {
* @exaple SAVE variable as "my.txt"
*
*/
public async saveFile(file: any, data: any): Promise<any> {
public async saveFile({file, data}): Promise<any> {
GBLog.info(`BASIC: Saving '${file}' (SAVE file).`);
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
@ -556,7 +563,9 @@ export class SystemKeywords {
* @exaple SAVE "customers.xlsx", name, email, phone, address, city, state, country
*
*/
public async save(file: string, ...args): Promise<any> {
public async save({args}): Promise<any> {
const file = args[0];
args.shift();
GBLog.info(`BASIC: Saving '${file}' (SAVE). Args: ${args.join(',')}.`);
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const botId = this.min.instance.botId;
@ -597,11 +606,12 @@ export class SystemKeywords {
* @example value = GET "file.xlsx", "A2"
*
*/
public async get(file: string, addressOrHeaders: string, httpUsername, httpPs, qs, streaming): Promise<any> {
public async get({file, addressOrHeaders, httpUsername, httpPs, qs, streaming}): Promise<any> {
if (file.startsWith('http')) {
return await this.getByHttp(file, addressOrHeaders, httpUsername, httpPs, qs, streaming);
return await this.getByHttp({url:file, headers: addressOrHeaders, username: httpUsername,
ps: httpPs, qs, streaming});
}
else {
GBLog.info(`BASIC: GET '${addressOrHeaders}' in '${file}'.`);
@ -627,7 +637,7 @@ export class SystemKeywords {
}
}
public isValidDate(dt) {
public isValidDate({dt}) {
const contentLocale = this.min.core.getParam<string>(
this.min.instance,
'Default Content Language',
@ -646,12 +656,12 @@ export class SystemKeywords {
return !isNaN(date.valueOf());
}
public isValidNumber(number) {
public isValidNumber({number}) {
if (number === '') { return false }
return !isNaN(number);
}
public isValidHour(value) {
public isValidHour({value}) {
return /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/.test(value);
}
@ -671,7 +681,9 @@ export class SystemKeywords {
*
* // TODO: https://www.npmjs.com/package/parse-markdown-table
*/
public async find(file: string, ...args): Promise<any> {
public async find({args}): Promise<any> {
const file = args[0];
args.shift();
GBLog.info(`BASIC: FIND running on ${file} and args: ${JSON.stringify(args)}...`);
const botId = this.min.instance.botId;
@ -1051,7 +1063,7 @@ export class SystemKeywords {
*
* @example file = DOWNLOAD element, folder
*/
public async download(element, folder) {
public async download({element, folder}) {
const page = element['_page'];
const container = element['_frame'] ? element['_frame'] : element['_page'];
@ -1142,7 +1154,7 @@ export class SystemKeywords {
* @example folder = CREATE FOLDER "notes\01"
*
*/
public async createFolder(name: string) {
public async createFolder({name}) {
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const botId = this.min.instance.botId;
@ -1199,7 +1211,7 @@ export class SystemKeywords {
* SHARE FOLDER folder, "nome@domain.com", "E-mail message"
*
*/
public async shareFolder(folderReference, email: string, message: string) {
public async shareFolder({folderReference, email, message}) {
let [, client] = await GBDeployer.internalGetDriveClient(this.min);
const driveId = folderReference.parentReference.driveId;
const itemId = folderReference.id;
@ -1224,7 +1236,7 @@ export class SystemKeywords {
* COPY "template.xlsx", "reports\" + customerName + "\final.xlsx"
*
*/
public async copyFile(src, dest) {
public async copyFile({src, dest}) {
GBLog.info(`BASIC: BEGINING COPY '${src}' to '${dest}'`);
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const botId = this.min.instance.botId;
@ -1293,7 +1305,7 @@ export class SystemKeywords {
* CONVERT "customers.xlsx" TO "reports\" + today + ".pdf"
*
*/
public async convert(src, dest) {
public async convert({src, dest}) {
GBLog.info(`BASIC: CONVERT '${src}' to '${dest}'`);
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const botId = this.min.instance.botId;
@ -1375,7 +1387,7 @@ export class SystemKeywords {
* @example user = get "http://server/users/1"
*
*/
public async getByHttp(url: string, headers: any, username: string, ps: string, qs: any, streaming = false) {
public async getByHttp({url, headers, username, ps, qs, streaming}) {
let options = { url: url };
if (headers) {
options['headers'] = headers;
@ -1415,7 +1427,7 @@ export class SystemKeywords {
* talk "The updated user area is" + user.area
*
*/
public async putByHttp(url: string, data, headers) {
public async putByHttp({url, data, headers}) {
const options = {
uri: url,
json: data,
@ -1436,7 +1448,7 @@ export class SystemKeywords {
* talk "The updated user area is" + user.area
*
*/
public async postByHttp(url: string, data, headers) {
public async postByHttp({url, data, headers}) {
const options = {
uri: url,
json: data,
@ -1460,7 +1472,7 @@ export class SystemKeywords {
* doc = FILL "templates/template.docx", data
*
*/
public async fill(templateName, data) {
public async fill({templateName, data}) {
const botId = this.min.instance.botId;
const gbaiName = `${botId}.gbai`;
@ -1555,7 +1567,7 @@ export class SystemKeywords {
* MERGE "second.xlsx" WITH data BY customer_id
*
*/
public async merge(file: string, data: [], key1, key2): Promise<any> {
public async merge({file, data, key1, key2}): Promise<any> {
GBLog.info(`BASIC: MERGE running on ${file} and key1: ${key1}, key2: ${key2}...`);
const botId = this.min.instance.botId;
@ -1658,19 +1670,19 @@ export class SystemKeywords {
if (value !== found[columnName]) {
await this.set(file, address, value);
await this.set({file, address, value});
merges++;
}
}
}
else {
let args = [];
let args = [file];
let keys = Object.keys(row);
for (let j = 0; j < keys.length; j++) {
args.push(row[keys[j]]);
}
await this.save(file, ...args);
await this.save({args});
adds++;
}
}
@ -1684,7 +1696,7 @@ export class SystemKeywords {
}
}
public async tweet(text: string) {
public async tweet({text}) {
const consumer_key = this.min.core.getParam(this.min.instance, 'Twitter Consumer Key', null);
const consumer_secret = this.min.core.getParam(this.min.instance, 'Twitter Consumer Key Secret', null);
@ -1704,7 +1716,5 @@ export class SystemKeywords {
await client.v2.tweet(text);
GBLog.info(`Twitter Automation: ${text}.`);
}
}

View file

@ -66,7 +66,7 @@ export class TSCompiler {
noImplicitUseStrict: true,
noEmitOnError: false,
noImplicitAny: true,
target: ts.ScriptTarget.ES5,
target: ts.ScriptTarget.ESNext,
module: ts.ModuleKind.None,
moduleResolution: ts.ModuleResolutionKind.Classic,
noEmitHelpers: true,

View file

@ -36,10 +36,10 @@ const server = net1.createServer((socket) => {
});
console.log(JSON.stringify({ result }));
debugger;
socket.write(JSON.stringify({ result }) + '\n');
socket.end();
} catch (error) {
console.log(`BASIC: RUNTIME: ${error.message}, ${error.stack}`)
socket.write(JSON.stringify({ error: error.message }) + '\n');
socket.end();
}