new(all): Vm isolated working with IPC BASIC 3.0;
This commit is contained in:
parent
45f4a48f88
commit
4bbd384501
5 changed files with 335 additions and 320 deletions
|
@ -2,7 +2,7 @@
|
|||
| ( )_ _ |
|
||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
|
||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) ) |
|
||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
||||
| | | ( )_) | |
|
||||
| (_) \___/' |
|
||||
|
@ -10,22 +10,22 @@
|
|||
| 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 |
|
||||
| permission and of our proprietary license can be found at and |
|
||||
| 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 |
|
||||
| This program is distributed in the hope that it will be useful, |
|
||||
| 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");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}.`);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue