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

This commit is contained in:
rodrigorodriguez 2022-11-06 20:19:05 -03:00
parent fa0324dc06
commit 25230816b0
7 changed files with 2191 additions and 395 deletions

2456
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -83,11 +83,13 @@
"botframework-connector": "4.11.0",
"botlib": "1.10.9",
"c3-chart-maker": "^0.2.8",
"chrome-remote-interface": "^0.31.3",
"cli-progress": "^3.11.2",
"cli-spinner": "0.2.10",
"core-js": "3.14.0",
"data-forge": "^1.9.5",
"date-diff": "0.2.2",
"debugger-api": "^0.1.2",
"docxtemplater": "^3.31.1",
"dotenv-extended": "2.9.0",
"exceljs": "4.2.1",

View file

@ -482,7 +482,7 @@ export class DialogKeywords {
/**
* Returns current time in format hh:dd.
*
* @example SAVE "file.xlsx",name,email,NOW
* @example SAVE "contacts.xlsx", name, email, NOW
*
*/
public async getNow({}) {

View file

@ -51,6 +51,8 @@ const walkPromise = require('walk-promise');
const child_process = require('child_process');
const Path = require('path');
/**
* @fileoverview Virtualization services for emulation of BASIC.
* This alpha version is using a antipattern hack in form of converter to
@ -168,12 +170,17 @@ export class GBVMService extends GBService {
let basicCode: string = fs.readFileSync(filename, 'utf8');
// Processes END keyword, removing extracode, useful
// for development.
// for development in .gbdialog.
// TODO: let end = /(\nend\n)/gi.exec(basicCode);
// if (end) {
// basicCode = basicCode.substring(0, end.index);
// }
if (process.env.GBDIALOG_NOEND === 'true') {
basicCode = basicCode.replace(/(^|\W)END(\W|\n)/gi, '');
}
else {
let end = /(^|\W)END(\W|\n)/gi.exec(basicCode);
if (end) {
basicCode = basicCode.substring(0, end.index);
}
}
// Removes comments.
@ -274,7 +281,7 @@ export class GBVMService extends GBService {
`;
// Finds all hear calls.
const parsedCode = beautify(code, { indent_size: 2, space_in_empty_paren: true });
const parsedCode = beautify(code, { indent_size: 2, space_in_empty_paren: true, preserve_newlines: true, wrap_line_length: 240 });
fs.writeFileSync(jsfile, parsedCode);
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
@ -332,13 +339,24 @@ export class GBVMService extends GBService {
`;
const getParams = async (text, names) => {
// Split all params by comma, not inside strings.
const getParams = (text, names) => {
let ret = {};
const items = text.split(','); // TODO: NOT IN STRING.
const items = text.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g);
await CollectionUtil.asyncForEach(names, async name => {
ret[name] = items[0];
let i = 0;
names.forEach(name => {
let value = items[i];
// Add string to JSON without quotes.
if (value && (value.charAt(0) === '"' || value.charAt(0) === '\'')) {
value = value.substr(1, value.length - 2);
}
ret[name] = value;
i++;
});
return JSON.stringify(ret);
@ -352,8 +370,13 @@ export class GBVMService extends GBService {
return `${$1} = await sys.executeSQL({data:${$1}, sql:"${sql}", tableName:"${tableName}"})\n`;
});
code = code.replace(/get html\s*(.*)/gi, ($0, $1, $2) => {
const params = getParams($2, ['url', 'username', 'password']);
code = code.replace(/open\s*(.*)/gi, ($0, $1, $2) => {
if (!$1.startsWith("\"") && $1.startsWith("\'")) {
$1 = `"${$1}"`;
}
const params = getParams($1, ['url', 'username', 'password']);
return `page = await wa.getPage(${params})\n`;
});
@ -410,7 +433,7 @@ export class GBVMService extends GBService {
});
code = code.replace(/hear (\w+) as (.*)/gi, ($0, $1, $2) => {
return `${$1} = await dk.getHear({kind:"menu", [${$2}])}`;
return `${$1} = await dk.getHear({kind:"menu", args: [${$2}])}`;
});
code = code.replace(/(hear)\s*(\w+)/gi, ($0, $1, $2) => {
@ -430,8 +453,8 @@ export class GBVMService extends GBService {
`;
});
code = code.replace(/CALL\s*(.*)/gi, ($0, $1, $2, $3) => {
return `await sys.callVM("${$1}", dk.getMin(), dk.getStep(), dk.getDeployer())\n`;
code = code.replace(/CALL\s*(.*)/gi, ($0, $1) => {
return `await ${$1}\n`;
});
code = code.replace(/(\w)\s*\=\s*find\s*(.*)/gi, ($0, $1, $2, $3) => {
@ -583,12 +606,6 @@ export class GBVMService extends GBService {
return `await sys.createABotFarmUsing ({${$3}})`;
});
code = code.replace(/(chart)(\s)(.*)/gi, ($0, $1, $2, $3) => {
const params = getParams($3, ['type', 'data', 'legends', 'transpose']);
return `await dk.chart (${params})\n`;
});
code = code.replace(/(transfer to)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await dk.transferTo ({to:${$3}})\n`;
});
@ -667,10 +684,14 @@ export class GBVMService extends GBService {
return `await sys.convert (${params})\n`;
});
// TODO: AS CHART.
// code = code.replace(/(\w+)\s*\=\s*(.*)\s*as chart/gi, ($0, $1, $2) => {
// return `${$1} = await sys.asImage({${$2})\n`;
// });
code = code.replace(/(\w+)\s*\=\s*(.*)\s*as chart/gi, ($0, $1, $2) => {
return `await dk.chart ({type:'bar', data: ${2}, legends:null, transpose: false})\n`;
});
code = code.replace(/(chart)(\s)(.*)/gi, ($0, $1, $2, $3) => {
const params = getParams($3, ['type', 'data', 'legends', 'transpose']);
return `await dk.chart (${params})\n`;
});
code = code.replace(/MERGE\s(.*)\sWITH\s(.*)BY\s(.*)/gi, ($0, $1, $2, $3) => {
return `await sys.merge({file: ${$1}, data: ${$2}, key1: ${$3}})\n`;
@ -697,14 +718,14 @@ export class GBVMService extends GBService {
});
code = code.replace(/(\w+)\s*\=\s*FILL\s(.*)\sWITH\s(.*)/gi, ($0, $1, $2, $3) => {
return `${1} = await sys.fill({templateName: ${$2}, data: ${$3}})\n`;
return `${$1} = await sys.fill({templateName: ${$2}, data: ${$3}})\n`;
});
code = code.replace(/save\s(.*)\sas\s(.*)/gi, ($0, $1, $2, $3) => {
return `await sys.saveFile({file: ${$2}, data: ${$1})\n`;
});
code = code.replace(/(save)(\s)(.*)/gi, ($0, $1, $2, $3) => {
return `await sys.save({[${$3}]})\n`;
return `await sys.save({args: [${$3}]})\n`;
});
code = code.replace(/set\s(.*)/gi, ($0, $1, $2) => {
@ -784,6 +805,7 @@ export class GBVMService extends GBService {
const { run, drain } = createVm2Pool({
min: 1,
max: 1,
debuggerPort: 9222,
cpu: 100,
memory: 50000,
time: 60 * 60 * 24 * 14,
@ -791,6 +813,7 @@ export class GBVMService extends GBService {
script: runnerPath
});
const port = run.port;
const result = await run(code, { filename: scriptPath, sandbox: sandbox });
drain();

View file

@ -554,7 +554,6 @@ export class SystemKeywords {
}
throw error;
}
}
/**
@ -1121,14 +1120,16 @@ export class SystemKeywords {
* SHARE FOLDER folder, "nome@domain.com", "E-mail message"
*
*/
public async shareFolder({folderReference, email, message}) {
public async shareFolder({folder, email, message}) {
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
const srcFile = await client.api(
`${baseUrl}/drive/root:/${folder}`)
const root = urlJoin(`/${this.min.botId}.gbai/${this.min.botId}.gbdrive`, folder);
const src = await client.api(
`${baseUrl}/drive/root:/${root}`)
.get();
const driveId = folderReference.parentReference.driveId;
const itemId = folderReference.id;
const driveId = src.parentReference.driveId;
const itemId = src.id;
const body = {
"recipients": [{ "email": email }],
"message": message,

View file

@ -2,7 +2,7 @@ const crypto2 = require('crypto');
const Fs = require('fs');
const Path = require('path');
const { spawn } = require('child_process');
const CDP = require('chrome-remote-interface');
const { } = require('child_process');
const { dirname } = require('path');
const { fileURLToPath } = require('url');
@ -50,7 +50,7 @@ const createVm2Pool = ({ min, max, ...limits }) => {
const runner = spawn('cpulimit', [
'-ql', limits.cpu,
'--',
'node', `--experimental-fetch`, `--max-old-space-size=${limits.memory}`,
'node', `--inspect-brk=${limits.debuggerPort} --experimental-fetch`, `--max-old-space-size=${limits.memory}`,
limits.script
, ref
], { cwd: limits.cwd, shell: false });
@ -79,6 +79,25 @@ const createVm2Pool = ({ min, max, ...limits }) => {
const run = async (code, scope) => {
const childProcess = await pool.acquire();
CDP(async (client) => {
const { Debugger, Runtime } = client;
try {
client.Debugger.paused(() => {
client.Debugger.resume();
client.close();
});
await client.Runtime.runIfWaitingForDebugger();
await client.Debugger.enable();
} catch (err) {
console.error(err);
} finally {
client.close();
}
}).on('error', (err) => {
console.error(err);
});
await waitUntil(() => childProcess.socket);
const socket = net.createConnection(childProcess.socket);

View file

@ -53,7 +53,7 @@ import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer';
import { GBImporter } from '../packages/core.gbapp/services/GBImporterService';
import { GBMinService } from '../packages/core.gbapp/services/GBMinService';
var auth = require('basic-auth');
const child_process = require('child_process');
/**
* Global shared server data;
@ -83,12 +83,21 @@ export class GBServer {
public static run() {
GBLog.info(`The Bot Server is in STARTING mode...`);
GBServer.globals = new RootData();
GBConfigService.init();
const port = GBConfigService.getServerPort();
if (process.env.TEST_SHELL)
{
GBLog.info(`Running TEST_SHELL: ${process.env.TEST_SHELL}...`);
try{
child_process.execSync(process.env.TEST_SHELL);
}catch(error){
GBLog.error(`Running TEST_SHELL ERROR: ${error}...`);
}
}
const server = express();