From 3f32e48fad3635b3e29365cbd019a16fea36fd39 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (pragmatismo.io)" Date: Wed, 28 Nov 2018 17:08:06 -0200 Subject: [PATCH] fix(core): Loaded dynamically a .js file containing converted VBA dialogs. --- packages/core.gbapp/services/GBAPIService.ts | 7 +-- packages/core.gbapp/services/GBCoreService.ts | 45 +++++++++---------- packages/core.gbapp/services/GBDeployer.ts | 9 ++-- .../core.gbapp/services/GBImporterService.ts | 40 ++++++----------- packages/core.gbapp/services/GBMinService.ts | 8 +++- packages/core.gbapp/services/GBVMService.ts | 13 +++--- packages/default.gbdialog/bot.vbs.js | 8 +++- packages/kb.gbapp/dialogs/AskDialog.ts | 16 +++---- packages/kb.gbapp/dialogs/MenuDialog.ts | 2 +- src/app.ts | 22 ++++++--- 10 files changed, 89 insertions(+), 81 deletions(-) diff --git a/packages/core.gbapp/services/GBAPIService.ts b/packages/core.gbapp/services/GBAPIService.ts index 70acdf7d..f489fcb0 100644 --- a/packages/core.gbapp/services/GBAPIService.ts +++ b/packages/core.gbapp/services/GBAPIService.ts @@ -33,16 +33,16 @@ 'use strict'; import { WaterfallDialog } from 'botbuilder-dialogs'; -import { IGBInstance, IGBPackage } from 'botlib'; +import { IGBInstance, IGBPackage ,GBMinInstance } from 'botlib'; /** * @fileoverview General Bots server core. */ export class DialogClass { - public min: IGBInstance; + public min: GBMinInstance; - constructor(min: IGBInstance) { + constructor(min: GBMinInstance) { this.min = min; } @@ -72,6 +72,7 @@ export class DialogClass { new WaterfallDialog('/vmSend', [ async step => { await step.context.sendActivity(text); + return await step.next(); } ]) diff --git a/packages/core.gbapp/services/GBCoreService.ts b/packages/core.gbapp/services/GBCoreService.ts index a7f6256d..4d0f4ca3 100644 --- a/packages/core.gbapp/services/GBCoreService.ts +++ b/packages/core.gbapp/services/GBCoreService.ts @@ -184,8 +184,9 @@ export class GBCoreService implements IGBCoreService { alter: alter, force: force }); + } else { - const msg = 'Database synchronization is disabled.'; + const msg = `Database synchronization is disabled.`; logger.info(msg); } } @@ -218,21 +219,21 @@ export class GBCoreService implements IGBCoreService { public async writeEnv(instance: IGBInstance) { const env = `ADDITIONAL_DEPLOY_PATH= - ADMIN_PASS=${instance.adminPass} - CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId} - CLOUD_LOCATION=${instance.cloudLocation} - CLOUD_GROUP=${instance.botId} - CLOUD_USERNAME=${instance.cloudUsername} - CLOUD_PASSWORD=${instance.cloudPassword} - MARKETPLACE_ID=${instance.marketplaceId} - MARKETPLACE_SECRET=${instance.marketplacePassword} - NLP_AUTHORING_KEY=${instance.nlpAuthoringKey} - STORAGE_DIALECT=${instance.storageDialect} - STORAGE_SERVER=${instance.storageServer}.database.windows.net - STORAGE_NAME=${instance.storageName} - STORAGE_USERNAME=${instance.storageUsername} - STORAGE_PASSWORD=${instance.storagePassword} - STORAGE_SYNC=true`; + ADMIN_PASS=${instance.adminPass} + CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId} + CLOUD_LOCATION=${instance.cloudLocation} + CLOUD_GROUP=${instance.botId} + CLOUD_USERNAME=${instance.cloudUsername} + CLOUD_PASSWORD=${instance.cloudPassword} + MARKETPLACE_ID=${instance.marketplaceId} + MARKETPLACE_SECRET=${instance.marketplacePassword} + NLP_AUTHORING_KEY=${instance.nlpAuthoringKey} + STORAGE_DIALECT=${instance.storageDialect} + STORAGE_SERVER=${instance.storageServer}.database.windows.net + STORAGE_NAME=${instance.storageName} + STORAGE_USERNAME=${instance.storageUsername} + STORAGE_PASSWORD=${instance.storagePassword} + STORAGE_SYNC=true`; fs.writeFileSync('.env', env); } @@ -312,6 +313,7 @@ export class GBCoreService implements IGBCoreService { } public loadSysPackages(core: GBCoreService) { + // NOTE: if there is any code before this line a semicolon // will be necessary before this line. // Loads all system packages. @@ -342,26 +344,21 @@ export class GBCoreService implements IGBCoreService { public async createBootInstance(core: GBCoreService, azureDeployer: AzureDeployerService, proxyAddress: string) { let instance: IGBInstance; - try { - await core.initStorage(); - } catch (error) { logger.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`); try { instance = await azureDeployer.deployFarm(proxyAddress); } catch (error) { logger.warn( - 'In case of error, please cleanup any infrastructure objects ' + - 'created during this procedure and .env before running again.' + `In case of error, please cleanup any infrastructure objects + created during this procedure and .env before running again.` ); throw error; } core.writeEnv(instance); logger.info(`File .env written, starting General Bots...`); GBConfigService.init(); - await core.initStorage(); - return instance; - } + return instance; } public openBrowserInDevelopment() { diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index 1d0b15de..b79eff07 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -43,7 +43,7 @@ const Fs = require('fs'); const WaitUntil = require('wait-until'); const express = require('express'); -import { IGBCoreService, IGBInstance } from 'botlib'; +import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib'; import { GBError } from 'botlib'; import { IGBPackage } from 'botlib'; import { AzureSearch } from 'pragmatismo-io-framework'; @@ -174,9 +174,11 @@ export class GBDeployer { /** Deploys all .gbot files first. */ botPackages.forEach(e => { + if (e!=='packages\\boot.gbot'){ logger.info(`Deploying bot: ${e}...`); _this.deployBot(e); logger.info(`Bot: ${e} deployed...`); + } }); /** Then all remaining generalPackages are loaded. */ @@ -251,10 +253,11 @@ export class GBDeployer { public async deployBot(localPath: string): Promise { const packageType = Path.extname(localPath); const packageName = Path.basename(localPath); - const instance = await this.importer.importIfNotExistsBotPackage( + const instance = await this.importer.importIfNotExistsBotPackage(null, packageName, localPath ); + return instance; } @@ -282,7 +285,7 @@ export class GBDeployer { // }) } - public async deployPackageFromLocalPath(min: IGBInstance, localPath: string) { + public async deployPackageFromLocalPath(min: GBMinInstance, localPath: string) { const packageType = Path.extname(localPath); switch (packageType) { diff --git a/packages/core.gbapp/services/GBImporterService.ts b/packages/core.gbapp/services/GBImporterService.ts index 04bf1208..65745089 100644 --- a/packages/core.gbapp/services/GBImporterService.ts +++ b/packages/core.gbapp/services/GBImporterService.ts @@ -50,41 +50,29 @@ export class GBImporter { this.core = core; } - public async importIfNotExistsBotPackage( - packageName: string, - localPath: string) { - - const packageJson = JSON.parse( - fs.readFileSync(UrlJoin(localPath, 'package.json'), 'utf8') - ); - const botId = packageJson.botId; + public async importIfNotExistsBotPackage(botId: string, packageName: string, localPath: string) { + const packageJson = JSON.parse(fs.readFileSync(UrlJoin(localPath, 'package.json'), 'utf8')); + if (!botId) { + botId = packageJson.botId; + } const instance = await this.core.loadInstance(botId); if (instance) { return instance; } else { - return await this.createInstanceInternal(packageName, localPath, packageJson); + return await this.createInstanceInternal(botId, packageName, localPath, packageJson); } } - private async createInstanceInternal( - packageName: string, - localPath: string, - packageJson: any - ) { - const settings = JSON.parse( - fs.readFileSync(UrlJoin(localPath, 'settings.json'), 'utf8') - ); - const servicesJson = JSON.parse( - fs.readFileSync(UrlJoin(localPath, 'services.json'), 'utf8') - ); + private async createInstanceInternal(botId: string, packageName: string, localPath: string, packageJson: any) { + const settings = JSON.parse(fs.readFileSync(UrlJoin(localPath, 'settings.json'), 'utf8')); + const servicesJson = JSON.parse(fs.readFileSync(UrlJoin(localPath, 'services.json'), 'utf8')); - packageJson = {...packageJson, ...settings, ...servicesJson}; + packageJson = { ...packageJson, ...settings, ...servicesJson }; - GuaribasInstance.create(packageJson).then((instance: IGBInstance) => { - const service = new SecService(); - // TODO: service.importSecurityFile(localPath, instance) + if (botId){ + packageJson.botId = botId; + } - Promise.resolve(instance); - }); + return GuaribasInstance.create(packageJson); } } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index fded27ab..eb974773 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -110,7 +110,8 @@ export class GBMinService { public async buildMin( server: any, appPackages: IGBPackage[], - instances: GuaribasInstance[] + instances: GuaribasInstance[], + deployer: GBDeployer ): Promise { // Serves default UI on root address '/'. @@ -169,6 +170,11 @@ export class GBMinService { instance ); + // Install default VBA module. + + deployer.deployPackageFromLocalPath(min, 'packages/default.gbdialog'); + + // Call the loadBot context.activity for all packages. this.invokeLoadBot(appPackages, min, server); diff --git a/packages/core.gbapp/services/GBVMService.ts b/packages/core.gbapp/services/GBVMService.ts index 9e81174f..4249f6b9 100644 --- a/packages/core.gbapp/services/GBVMService.ts +++ b/packages/core.gbapp/services/GBVMService.ts @@ -33,8 +33,7 @@ 'use strict'; import { IGBCoreService, IGBInstance } from 'botlib'; -import { GBError } from 'botlib'; -import { IGBPackage } from 'botlib'; +import { GBMinInstance } from 'botlib'; const logger = require('../../../src/logger'); import { BotAdapter } from 'botbuilder'; import { WaterfallDialog } from 'botbuilder-dialogs'; @@ -57,18 +56,20 @@ export class GBVMService implements IGBCoreService { public async loadJS( filename: string, - min: IGBInstance, + min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer, localPath: string ): Promise { - localPath = UrlJoin(localPath, 'chat.dialog.js'); - const code: string = fs.readFileSync(UrlJoin(localPath, filename), 'utf8'); + + localPath = UrlJoin(localPath, 'bot.vbs.js'); + const code: string = fs.readFileSync(localPath, 'utf8'); const sandbox: DialogClass = new DialogClass(min); const context = vm.createContext(sandbox); - this.script.runInContext(code, context); + vm.runInContext(code, context); console.log(util.inspect(sandbox)); + sandbox['chat'](sandbox); await deployer.deployScriptToStorage(min.instanceId, filename); logger.info(`[GBVMService] Finished loading of ${filename}`); diff --git a/packages/default.gbdialog/bot.vbs.js b/packages/default.gbdialog/bot.vbs.js index 6e2c001a..c18aa941 100644 --- a/packages/default.gbdialog/bot.vbs.js +++ b/packages/default.gbdialog/bot.vbs.js @@ -1,4 +1,6 @@ -export function chat() { + +function chat(bot) { + //**************************************************************************** // ( )_ _ // _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ @@ -31,11 +33,13 @@ export function chat() { // //**************************************************************************** + bot.talk('Qual seu e-mail?'); + main = () => { bot.addFunction(PegaEmail); PegaEmail = bot => { - bot.say('Qual seu e-mail?'); + bot.talk('Qual seu e-mail?'); email = bot.expectEmail; bot.post('/restservice', email); }; diff --git a/packages/kb.gbapp/dialogs/AskDialog.ts b/packages/kb.gbapp/dialogs/AskDialog.ts index 6a804bbf..076f965b 100644 --- a/packages/kb.gbapp/dialogs/AskDialog.ts +++ b/packages/kb.gbapp/dialogs/AskDialog.ts @@ -59,10 +59,10 @@ export class AskDialog extends IGBDialog { min.dialogs.add( new WaterfallDialog('/answerEvent', [ async step => { - if (step.options && step.options.questionId) { + if (step.options && step.options['questionId']) { const question = await service.getQuestionById( min.instance.instanceId, - step.options.questionId + step.options['questionId'] ); const answer = await service.getAnswerById( min.instance.instanceId, @@ -84,7 +84,7 @@ export class AskDialog extends IGBDialog { new WaterfallDialog('/answer', [ async step => { const user = await min.userProfile.get(step.context, {}); - let text = step.options.query; + let text = step.options['query']; if (!text) { throw new Error(`/answer being called with no args query text.`); } @@ -97,9 +97,9 @@ export class AskDialog extends IGBDialog { // Handle extra text from FAQ. - if (step.options && step.options.query) { - text = step.options.query; - } else if (step.options && step.options.fromFaq) { + if (step.options && step.options['query']) { + text = step.options['query']; + } else if (step.options && step.options['fromFaq']) { await step.context.sendActivity(Messages[locale].going_answer); } @@ -212,9 +212,9 @@ export class AskDialog extends IGBDialog { // Three forms of asking. - if (step.options && step.options.firstTime) { + if (step.options && step.options['firstTime']) { text = Messages[locale].ask_first_time; - } else if (step.options && step.options.isReturning) { + } else if (step.options && step.options['isReturning']) { text = Messages[locale].anything_else; } else if (user.subjects.length > 0) { text = Messages[locale].which_question; diff --git a/packages/kb.gbapp/dialogs/MenuDialog.ts b/packages/kb.gbapp/dialogs/MenuDialog.ts index 5ae6441f..fece9fc0 100644 --- a/packages/kb.gbapp/dialogs/MenuDialog.ts +++ b/packages/kb.gbapp/dialogs/MenuDialog.ts @@ -63,7 +63,7 @@ export class MenuDialog extends IGBDialog { const locale = step.context.activity.locale; let rootSubjectId = null; - if (step.options && step.options.data) { + if (step.options && step.options['data']) { const subject = step.result.data; // If there is a shortcut specified as subject destination, go there. diff --git a/src/app.ts b/src/app.ts index 1f87ab6a..1c1b897a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -103,24 +103,32 @@ export class GBServer { const conversationalService: GBConversationalService = new GBConversationalService(core); core.ensureAdminIsSecured(); - const bootInstance = await core.createBootInstance(core, azureDeployer, proxyAddress); - await core.checkStorage(azureDeployer); + let bootInstance: IGBInstance = null; + try { + await core.initStorage(); + } catch (error) { + bootInstance = await core.createBootInstance(core, azureDeployer, proxyAddress); + await core.initStorage(); + } + await core.loadSysPackages(core); + await core.checkStorage(azureDeployer); await deployer.deployPackages(core, server, appPackages); logger.info(`Publishing instances...`); - const packageInstance = await importer.importIfNotExistsBotPackage('boot.gbot', 'packages/boot.gbot'); + const packageInstance = await importer.importIfNotExistsBotPackage( + GBConfigService.get('CLOUD_GROUP'), + 'boot.gbot', + 'packages/boot.gbot' + ); const fullInstance = Object.assign(packageInstance, bootInstance); await core.saveInstance(fullInstance); let instances: GuaribasInstance[] = await core.loadAllInstances(core, azureDeployer, proxyAddress); instances = await core.ensureInstances(instances, bootInstance, core); - // Install default VBA module. - - deployer.deployPackageFromLocalPath(instances[0], 'packages/default.gbdialog'); const minService: GBMinService = new GBMinService(core, conversationalService, adminService, deployer); - await minService.buildMin(server, appPackages, instances); + await minService.buildMin(server, appPackages, instances, deployer); logger.info(`The Bot Server is in RUNNING mode...`); core.openBrowserInDevelopment();