diff --git a/packages/admin.gbapp/dialogs/AdminDialog.ts b/packages/admin.gbapp/dialogs/AdminDialog.ts index fd4d85deb..cc68228f3 100644 --- a/packages/admin.gbapp/dialogs/AdminDialog.ts +++ b/packages/admin.gbapp/dialogs/AdminDialog.ts @@ -72,7 +72,6 @@ export class AdminDialog extends IGBDialog { const importer = new GBImporter(min.core); const deployer = new GBDeployer(min.core, importer); - const adminService = new GBAdminService(min.core); AdminDialog.setupSecurityDialogs(min); diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 1d8d569e7..7d3a574c6 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -70,6 +70,8 @@ import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirect import fs = require('fs'); import { GuaribasConversationMessage } from '../../analytics.gblib/models'; import { GBCoreService } from './GBCoreService'; +import { DialogClass } from './GBAPIService'; +import { GBVMService } from './GBVMService'; /** * Minimal service layer for a bot. @@ -712,7 +714,7 @@ export class GBMinService { if (hasBadWord) { await step.beginDialog('/pleaseNoBadWords'); } 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) === '/') { let text = context.activity.text; 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); - } } diff --git a/packages/core.gbapp/services/GBVMService.ts b/packages/core.gbapp/services/GBVMService.ts index 058031839..c10e87032 100644 --- a/packages/core.gbapp/services/GBVMService.ts +++ b/packages/core.gbapp/services/GBVMService.ts @@ -33,18 +33,18 @@ 'use strict'; 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 { GBDeployer } from './GBDeployer'; import { TSCompiler } from './TSCompiler'; import { CollectionUtil } from 'pragmatismo-io-framework'; const walkPromise = require('walk-promise'); -const vm = require('vm'); import urlJoin = require('url-join'); import { DialogClass } from './GBAPIService'; import { Messages } from '../strings'; import { GBConversationalService } from './GBConversationalService'; //tslint:disable-next-line:no-submodule-imports +const vm = require('vm'); const vb2ts = require('vbscript-to-typescript/dist/converter'); const beautify = require('js-beautify').js; var textract = require('textract'); @@ -62,15 +62,12 @@ var textract = require('textract'); * Basic services for BASIC manipulation. */ export class GBVMService extends GBService { - private readonly script = new vm.Script(); - public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) { const files = await walkPromise(folder); this.addHearDialog(min); await CollectionUtil.asyncForEach(files, async file => { if (!file) { - return; } @@ -85,12 +82,11 @@ export class GBVMService extends GBService { let writeVBS = true; if (fs.existsSync(fullVbsFile)) { const vbsStat = fs.statSync(fullVbsFile); - if (docxStat.mtimeMs < (vbsStat.mtimeMs + interval)) { + if (docxStat.mtimeMs < vbsStat.mtimeMs + interval) { writeVBS = false; } } if (writeVBS) { - let text = await this.getTextFromWord(folder, wordFile); fs.writeFileSync(urlJoin(folder, vbsFile), text); } @@ -113,39 +109,33 @@ export class GBVMService extends GBService { if (fs.existsSync(jsfile)) { const jsStat = fs.statSync(jsfile); 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); - } - else { + } else { const parsedCode: string = fs.readFileSync(jsfile, 'utf8'); this.executeJS(min, deployer, parsedCode, mainName); } - } - else { + } else { await this.executeBASIC(fullFilename, min, deployer, mainName); } - } }); } private async getTextFromWord(folder: string, filename: string) { return new Promise(async (resolve, reject) => { - textract.fromFileWithPath(urlJoin(folder, filename), { preserveLineBreaks: true }, - (error, text) => { - if (error) { - reject(error); - } - else { - text = text.replace('“', '\"'); - text = text.replace('”', '\"'); - text = text.replace('‘', '\''); - text = text.replace('’', '\''); - - - resolve(text); - } - }); + textract.fromFileWithPath(urlJoin(folder, filename), { preserveLineBreaks: true }, (error, text) => { + if (error) { + reject(error); + } else { + text = text.replace('“', '"'); + text = text.replace('”', '"'); + text = text.replace('‘', "'"); + text = text.replace('’', "'"); + + resolve(text); + } + }); }); } @@ -262,8 +252,8 @@ export class GBVMService extends GBService { parsedCode = code.substring(pos, pos + match1.index); parsedCode += ``; - parsedCode += `const ${promiseName}= async (step, ${variable}) => {` - parsedCode += ` return new Promise(async (resolve) => {` + parsedCode += `const ${promiseName}= async (step, ${variable}) => {`; + parsedCode += ` return new Promise(async (resolve) => {`; // Skips old construction and point to the async block. @@ -306,7 +296,7 @@ export class GBVMService extends GBService { 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); 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) { try { - const sandbox: DialogClass = new DialogClass(min, deployer); - const context = vm.createContext(sandbox); - vm.runInContext(parsedCode, context); - min.sandBoxMap[mainName.toLowerCase()] = sandbox; - } - catch (error) { + min.sandBoxMap[mainName.toLowerCase()] = parsedCode; + } catch (error) { GBLog.error(`[GBVMService] ERROR loading ${error}`); } } @@ -346,7 +332,6 @@ export class GBVMService extends GBService { return $1 === undefined ? 'this.sendFile' : $1; }); - // await insertion. 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); + } } diff --git a/packages/kb.gbapp/dialogs/AskDialog.ts b/packages/kb.gbapp/dialogs/AskDialog.ts index a15844f31..751e363c2 100644 --- a/packages/kb.gbapp/dialogs/AskDialog.ts +++ b/packages/kb.gbapp/dialogs/AskDialog.ts @@ -43,9 +43,11 @@ import { GBLog, GBMinInstance, IGBDialog, IGBPackage } from 'botlib'; import { Messages } from '../strings'; import { KBService } from './../services/KBService'; import { GuaribasAnswer } from '../models'; -import { GBMinService } from '../../../packages/core.gbapp/services/GBMinService'; import { SecService } from '../../security.gbapp/services/SecService'; 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. @@ -59,6 +61,7 @@ export class AskDialogArgs { * Handle the ask loop on knowledge base data or delegate to other services. */ export class AskDialog extends IGBDialog { + static deployer: any; /** * Setup dialogs flows and define services call. * @@ -67,6 +70,9 @@ export class AskDialog extends IGBDialog { */ public static setup(bot: BotAdapter, min: GBMinInstance) { 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('/answer', AskDialog.getAnswerDialog(min, service))); 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) { if (answer.content.endsWith('.docx')) { 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 { await service.sendAnswer(min, AskDialog.getChannel(step), step, answer); return await step.replaceDialog('/ask', { isReturning: true });