fix(core.gbapp): Context in VM is isolated now.
This commit is contained in:
parent
4cb9d5b906
commit
42a7074081
4 changed files with 45 additions and 47 deletions
|
@ -72,7 +72,6 @@ export class AdminDialog extends IGBDialog {
|
||||||
|
|
||||||
const importer = new GBImporter(min.core);
|
const importer = new GBImporter(min.core);
|
||||||
const deployer = new GBDeployer(min.core, importer);
|
const deployer = new GBDeployer(min.core, importer);
|
||||||
const adminService = new GBAdminService(min.core);
|
|
||||||
|
|
||||||
AdminDialog.setupSecurityDialogs(min);
|
AdminDialog.setupSecurityDialogs(min);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,8 @@ import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirect
|
||||||
import fs = require('fs');
|
import fs = require('fs');
|
||||||
import { GuaribasConversationMessage } from '../../analytics.gblib/models';
|
import { GuaribasConversationMessage } from '../../analytics.gblib/models';
|
||||||
import { GBCoreService } from './GBCoreService';
|
import { GBCoreService } from './GBCoreService';
|
||||||
|
import { DialogClass } from './GBAPIService';
|
||||||
|
import { GBVMService } from './GBVMService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal service layer for a bot.
|
* Minimal service layer for a bot.
|
||||||
|
@ -712,7 +714,7 @@ export class GBMinService {
|
||||||
if (hasBadWord) {
|
if (hasBadWord) {
|
||||||
await step.beginDialog('/pleaseNoBadWords');
|
await step.beginDialog('/pleaseNoBadWords');
|
||||||
} else if (isVMCall) {
|
} else if (isVMCall) {
|
||||||
await GBMinService.callVM(context.activity.text, min, step);
|
await GBVMService.callVM(context.activity.text, min, step, this.deployer);
|
||||||
} else if (context.activity.text.charAt(0) === '/') {
|
} else if (context.activity.text.charAt(0) === '/') {
|
||||||
let text = context.activity.text;
|
let text = context.activity.text;
|
||||||
let parts = text.split(' ');
|
let parts = text.split(' ');
|
||||||
|
@ -803,9 +805,4 @@ export class GBMinService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async callVM(text: string, min: GBMinInstance, step: GBDialogStep) {
|
|
||||||
const mainMethod = text.toLowerCase();
|
|
||||||
min.sandBoxMap[mainMethod][mainMethod].bind(min.sandBoxMap[mainMethod]);
|
|
||||||
return await min.sandBoxMap[mainMethod][mainMethod](step);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,18 +33,18 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
import { GBLog, GBMinInstance, GBService, IGBCoreService } from 'botlib';
|
import { GBLog, GBMinInstance, GBService, IGBCoreService, GBDialogStep } from 'botlib';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { GBDeployer } from './GBDeployer';
|
import { GBDeployer } from './GBDeployer';
|
||||||
import { TSCompiler } from './TSCompiler';
|
import { TSCompiler } from './TSCompiler';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
const walkPromise = require('walk-promise');
|
const walkPromise = require('walk-promise');
|
||||||
const vm = require('vm');
|
|
||||||
import urlJoin = require('url-join');
|
import urlJoin = require('url-join');
|
||||||
import { DialogClass } from './GBAPIService';
|
import { DialogClass } from './GBAPIService';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings';
|
||||||
import { GBConversationalService } from './GBConversationalService';
|
import { GBConversationalService } from './GBConversationalService';
|
||||||
//tslint:disable-next-line:no-submodule-imports
|
//tslint:disable-next-line:no-submodule-imports
|
||||||
|
const vm = require('vm');
|
||||||
const vb2ts = require('vbscript-to-typescript/dist/converter');
|
const vb2ts = require('vbscript-to-typescript/dist/converter');
|
||||||
const beautify = require('js-beautify').js;
|
const beautify = require('js-beautify').js;
|
||||||
var textract = require('textract');
|
var textract = require('textract');
|
||||||
|
@ -62,15 +62,12 @@ var textract = require('textract');
|
||||||
* Basic services for BASIC manipulation.
|
* Basic services for BASIC manipulation.
|
||||||
*/
|
*/
|
||||||
export class GBVMService extends GBService {
|
export class GBVMService extends GBService {
|
||||||
private readonly script = new vm.Script();
|
|
||||||
|
|
||||||
public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) {
|
public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) {
|
||||||
const files = await walkPromise(folder);
|
const files = await walkPromise(folder);
|
||||||
this.addHearDialog(min);
|
this.addHearDialog(min);
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(files, async file => {
|
await CollectionUtil.asyncForEach(files, async file => {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,12 +82,11 @@ export class GBVMService extends GBService {
|
||||||
let writeVBS = true;
|
let writeVBS = true;
|
||||||
if (fs.existsSync(fullVbsFile)) {
|
if (fs.existsSync(fullVbsFile)) {
|
||||||
const vbsStat = fs.statSync(fullVbsFile);
|
const vbsStat = fs.statSync(fullVbsFile);
|
||||||
if (docxStat.mtimeMs < (vbsStat.mtimeMs + interval)) {
|
if (docxStat.mtimeMs < vbsStat.mtimeMs + interval) {
|
||||||
writeVBS = false;
|
writeVBS = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (writeVBS) {
|
if (writeVBS) {
|
||||||
|
|
||||||
let text = await this.getTextFromWord(folder, wordFile);
|
let text = await this.getTextFromWord(folder, wordFile);
|
||||||
fs.writeFileSync(urlJoin(folder, vbsFile), text);
|
fs.writeFileSync(urlJoin(folder, vbsFile), text);
|
||||||
}
|
}
|
||||||
|
@ -113,39 +109,33 @@ export class GBVMService extends GBService {
|
||||||
if (fs.existsSync(jsfile)) {
|
if (fs.existsSync(jsfile)) {
|
||||||
const jsStat = fs.statSync(jsfile);
|
const jsStat = fs.statSync(jsfile);
|
||||||
const interval = 30000; // If compiled is older 30 seconds, then recompile.
|
const interval = 30000; // If compiled is older 30 seconds, then recompile.
|
||||||
if (compiledAt.isFile() && compiledAt.mtimeMs > (jsStat.mtimeMs + interval)) {
|
if (compiledAt.isFile() && compiledAt.mtimeMs > jsStat.mtimeMs + interval) {
|
||||||
await this.executeBASIC(fullFilename, min, deployer, mainName);
|
await this.executeBASIC(fullFilename, min, deployer, mainName);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const parsedCode: string = fs.readFileSync(jsfile, 'utf8');
|
const parsedCode: string = fs.readFileSync(jsfile, 'utf8');
|
||||||
this.executeJS(min, deployer, parsedCode, mainName);
|
this.executeJS(min, deployer, parsedCode, mainName);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
await this.executeBASIC(fullFilename, min, deployer, mainName);
|
await this.executeBASIC(fullFilename, min, deployer, mainName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTextFromWord(folder: string, filename: string) {
|
private async getTextFromWord(folder: string, filename: string) {
|
||||||
return new Promise<string>(async (resolve, reject) => {
|
return new Promise<string>(async (resolve, reject) => {
|
||||||
textract.fromFileWithPath(urlJoin(folder, filename), { preserveLineBreaks: true },
|
textract.fromFileWithPath(urlJoin(folder, filename), { preserveLineBreaks: true }, (error, text) => {
|
||||||
(error, text) => {
|
if (error) {
|
||||||
if (error) {
|
reject(error);
|
||||||
reject(error);
|
} else {
|
||||||
}
|
text = text.replace('“', '"');
|
||||||
else {
|
text = text.replace('”', '"');
|
||||||
text = text.replace('“', '\"');
|
text = text.replace('‘', "'");
|
||||||
text = text.replace('”', '\"');
|
text = text.replace('’', "'");
|
||||||
text = text.replace('‘', '\'');
|
|
||||||
text = text.replace('’', '\'');
|
resolve(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
resolve(text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +252,8 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
parsedCode = code.substring(pos, pos + match1.index);
|
parsedCode = code.substring(pos, pos + match1.index);
|
||||||
parsedCode += ``;
|
parsedCode += ``;
|
||||||
parsedCode += `const ${promiseName}= async (step, ${variable}) => {`
|
parsedCode += `const ${promiseName}= async (step, ${variable}) => {`;
|
||||||
parsedCode += ` return new Promise(async (resolve) => {`
|
parsedCode += ` return new Promise(async (resolve) => {`;
|
||||||
|
|
||||||
// Skips old construction and point to the async block.
|
// Skips old construction and point to the async block.
|
||||||
|
|
||||||
|
@ -306,7 +296,7 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
parsedCode = this.handleThisAndAwait(parsedCode);
|
parsedCode = this.handleThisAndAwait(parsedCode);
|
||||||
|
|
||||||
parsedCode = beautify(parsedCode, { indent_size: 2, space_in_empty_paren: true })
|
parsedCode = beautify(parsedCode, { indent_size: 2, space_in_empty_paren: true });
|
||||||
fs.writeFileSync(jsfile, parsedCode);
|
fs.writeFileSync(jsfile, parsedCode);
|
||||||
|
|
||||||
this.executeJS(min, deployer, parsedCode, mainName);
|
this.executeJS(min, deployer, parsedCode, mainName);
|
||||||
|
@ -316,12 +306,8 @@ export class GBVMService extends GBService {
|
||||||
|
|
||||||
private executeJS(min: GBMinInstance, deployer: GBDeployer, parsedCode: string, mainName: string) {
|
private executeJS(min: GBMinInstance, deployer: GBDeployer, parsedCode: string, mainName: string) {
|
||||||
try {
|
try {
|
||||||
const sandbox: DialogClass = new DialogClass(min, deployer);
|
min.sandBoxMap[mainName.toLowerCase()] = parsedCode;
|
||||||
const context = vm.createContext(sandbox);
|
} catch (error) {
|
||||||
vm.runInContext(parsedCode, context);
|
|
||||||
min.sandBoxMap[mainName.toLowerCase()] = sandbox;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
GBLog.error(`[GBVMService] ERROR loading ${error}`);
|
GBLog.error(`[GBVMService] ERROR loading ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +332,6 @@ export class GBVMService extends GBService {
|
||||||
return $1 === undefined ? 'this.sendFile' : $1;
|
return $1 === undefined ? 'this.sendFile' : $1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// await insertion.
|
// await insertion.
|
||||||
|
|
||||||
code = code.replace(/this\./gm, 'await this.');
|
code = code.replace(/this\./gm, 'await this.');
|
||||||
|
@ -385,4 +370,15 @@ export class GBVMService extends GBService {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async callVM(text: string, min: GBMinInstance, step: GBDialogStep, deployer: GBDeployer) {
|
||||||
|
const sandbox: DialogClass = new DialogClass(min, deployer);
|
||||||
|
const context = vm.createContext(sandbox);
|
||||||
|
const code = min.sandBoxMap[text];
|
||||||
|
vm.runInContext(code, context);
|
||||||
|
|
||||||
|
const mainMethod = text.toLowerCase();
|
||||||
|
sandbox[mainMethod].bind(sandbox);
|
||||||
|
return await sandbox[mainMethod](step);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,11 @@ import { GBLog, GBMinInstance, IGBDialog, IGBPackage } from 'botlib';
|
||||||
import { Messages } from '../strings';
|
import { Messages } from '../strings';
|
||||||
import { KBService } from './../services/KBService';
|
import { KBService } from './../services/KBService';
|
||||||
import { GuaribasAnswer } from '../models';
|
import { GuaribasAnswer } from '../models';
|
||||||
import { GBMinService } from '../../../packages/core.gbapp/services/GBMinService';
|
|
||||||
import { SecService } from '../../security.gbapp/services/SecService';
|
import { SecService } from '../../security.gbapp/services/SecService';
|
||||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||||
|
import { GBVMService } from '../../core.gbapp/services/GBVMService';
|
||||||
|
import { GBImporter } from '../../core.gbapp/services/GBImporterService';
|
||||||
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog arguments.
|
* Dialog arguments.
|
||||||
|
@ -59,6 +61,7 @@ export class AskDialogArgs {
|
||||||
* Handle the ask loop on knowledge base data or delegate to other services.
|
* Handle the ask loop on knowledge base data or delegate to other services.
|
||||||
*/
|
*/
|
||||||
export class AskDialog extends IGBDialog {
|
export class AskDialog extends IGBDialog {
|
||||||
|
static deployer: any;
|
||||||
/**
|
/**
|
||||||
* Setup dialogs flows and define services call.
|
* Setup dialogs flows and define services call.
|
||||||
*
|
*
|
||||||
|
@ -67,6 +70,9 @@ export class AskDialog extends IGBDialog {
|
||||||
*/
|
*/
|
||||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||||
const service = new KBService(min.core.sequelize);
|
const service = new KBService(min.core.sequelize);
|
||||||
|
const importer = new GBImporter(min.core);
|
||||||
|
this.deployer = new GBDeployer(min.core, importer);
|
||||||
|
|
||||||
min.dialogs.add(new WaterfallDialog('/answerEvent', AskDialog.getAnswerEventDialog(service, min)));
|
min.dialogs.add(new WaterfallDialog('/answerEvent', AskDialog.getAnswerEventDialog(service, min)));
|
||||||
min.dialogs.add(new WaterfallDialog('/answer', AskDialog.getAnswerDialog(min, service)));
|
min.dialogs.add(new WaterfallDialog('/answer', AskDialog.getAnswerDialog(min, service)));
|
||||||
min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min)));
|
min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min)));
|
||||||
|
@ -259,7 +265,7 @@ export class AskDialog extends IGBDialog {
|
||||||
private static async handleAnswer(service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
|
private static async handleAnswer(service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
|
||||||
if (answer.content.endsWith('.docx')) {
|
if (answer.content.endsWith('.docx')) {
|
||||||
const mainName = answer.content.replace(/\s|\-/gi, '').split('.')[0];
|
const mainName = answer.content.replace(/\s|\-/gi, '').split('.')[0];
|
||||||
return await GBMinService.callVM(mainName, min, step);
|
return await GBVMService.callVM(mainName, min, step, this.deployer);
|
||||||
} else {
|
} else {
|
||||||
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
|
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
|
|
Loading…
Add table
Reference in a new issue