fix(core): Loaded dynamically a .js file containing converted VBA dialogs.

This commit is contained in:
Rodrigo Rodriguez (pragmatismo.io) 2018-11-28 17:08:06 -02:00
parent 1761e06061
commit 3f32e48fad
10 changed files with 89 additions and 81 deletions

View file

@ -33,16 +33,16 @@
'use strict'; 'use strict';
import { WaterfallDialog } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
import { IGBInstance, IGBPackage } from 'botlib'; import { IGBInstance, IGBPackage ,GBMinInstance } from 'botlib';
/** /**
* @fileoverview General Bots server core. * @fileoverview General Bots server core.
*/ */
export class DialogClass { export class DialogClass {
public min: IGBInstance; public min: GBMinInstance;
constructor(min: IGBInstance) { constructor(min: GBMinInstance) {
this.min = min; this.min = min;
} }
@ -72,6 +72,7 @@ export class DialogClass {
new WaterfallDialog('/vmSend', [ new WaterfallDialog('/vmSend', [
async step => { async step => {
await step.context.sendActivity(text); await step.context.sendActivity(text);
return await step.next(); return await step.next();
} }
]) ])

View file

@ -184,8 +184,9 @@ export class GBCoreService implements IGBCoreService {
alter: alter, alter: alter,
force: force force: force
}); });
} else { } else {
const msg = 'Database synchronization is disabled.'; const msg = `Database synchronization is disabled.`;
logger.info(msg); logger.info(msg);
} }
} }
@ -218,21 +219,21 @@ export class GBCoreService implements IGBCoreService {
public async writeEnv(instance: IGBInstance) { public async writeEnv(instance: IGBInstance) {
const env = `ADDITIONAL_DEPLOY_PATH= const env = `ADDITIONAL_DEPLOY_PATH=
ADMIN_PASS=${instance.adminPass} ADMIN_PASS=${instance.adminPass}
CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId} CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}
CLOUD_LOCATION=${instance.cloudLocation} CLOUD_LOCATION=${instance.cloudLocation}
CLOUD_GROUP=${instance.botId} CLOUD_GROUP=${instance.botId}
CLOUD_USERNAME=${instance.cloudUsername} CLOUD_USERNAME=${instance.cloudUsername}
CLOUD_PASSWORD=${instance.cloudPassword} CLOUD_PASSWORD=${instance.cloudPassword}
MARKETPLACE_ID=${instance.marketplaceId} MARKETPLACE_ID=${instance.marketplaceId}
MARKETPLACE_SECRET=${instance.marketplacePassword} MARKETPLACE_SECRET=${instance.marketplacePassword}
NLP_AUTHORING_KEY=${instance.nlpAuthoringKey} NLP_AUTHORING_KEY=${instance.nlpAuthoringKey}
STORAGE_DIALECT=${instance.storageDialect} STORAGE_DIALECT=${instance.storageDialect}
STORAGE_SERVER=${instance.storageServer}.database.windows.net STORAGE_SERVER=${instance.storageServer}.database.windows.net
STORAGE_NAME=${instance.storageName} STORAGE_NAME=${instance.storageName}
STORAGE_USERNAME=${instance.storageUsername} STORAGE_USERNAME=${instance.storageUsername}
STORAGE_PASSWORD=${instance.storagePassword} STORAGE_PASSWORD=${instance.storagePassword}
STORAGE_SYNC=true`; STORAGE_SYNC=true`;
fs.writeFileSync('.env', env); fs.writeFileSync('.env', env);
} }
@ -312,6 +313,7 @@ export class GBCoreService implements IGBCoreService {
} }
public loadSysPackages(core: GBCoreService) { public loadSysPackages(core: GBCoreService) {
// NOTE: if there is any code before this line a semicolon // NOTE: if there is any code before this line a semicolon
// will be necessary before this line. // will be necessary before this line.
// Loads all system packages. // Loads all system packages.
@ -342,26 +344,21 @@ export class GBCoreService implements IGBCoreService {
public async createBootInstance(core: GBCoreService, azureDeployer: AzureDeployerService, proxyAddress: string) { public async createBootInstance(core: GBCoreService, azureDeployer: AzureDeployerService, proxyAddress: string) {
let instance: IGBInstance; let instance: IGBInstance;
try {
await core.initStorage();
} catch (error) {
logger.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`); logger.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`);
try { try {
instance = await azureDeployer.deployFarm(proxyAddress); instance = await azureDeployer.deployFarm(proxyAddress);
} catch (error) { } catch (error) {
logger.warn( logger.warn(
'In case of error, please cleanup any infrastructure objects ' + `In case of error, please cleanup any infrastructure objects
'created during this procedure and .env before running again.' created during this procedure and .env before running again.`
); );
throw error; throw error;
} }
core.writeEnv(instance); core.writeEnv(instance);
logger.info(`File .env written, starting General Bots...`); logger.info(`File .env written, starting General Bots...`);
GBConfigService.init(); GBConfigService.init();
await core.initStorage();
return instance; return instance;
}
} }
public openBrowserInDevelopment() { public openBrowserInDevelopment() {

View file

@ -43,7 +43,7 @@ const Fs = require('fs');
const WaitUntil = require('wait-until'); const WaitUntil = require('wait-until');
const express = require('express'); const express = require('express');
import { IGBCoreService, IGBInstance } from 'botlib'; import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
import { GBError } from 'botlib'; import { GBError } from 'botlib';
import { IGBPackage } from 'botlib'; import { IGBPackage } from 'botlib';
import { AzureSearch } from 'pragmatismo-io-framework'; import { AzureSearch } from 'pragmatismo-io-framework';
@ -174,9 +174,11 @@ export class GBDeployer {
/** Deploys all .gbot files first. */ /** Deploys all .gbot files first. */
botPackages.forEach(e => { botPackages.forEach(e => {
if (e!=='packages\\boot.gbot'){
logger.info(`Deploying bot: ${e}...`); logger.info(`Deploying bot: ${e}...`);
_this.deployBot(e); _this.deployBot(e);
logger.info(`Bot: ${e} deployed...`); logger.info(`Bot: ${e} deployed...`);
}
}); });
/** Then all remaining generalPackages are loaded. */ /** Then all remaining generalPackages are loaded. */
@ -251,10 +253,11 @@ export class GBDeployer {
public async deployBot(localPath: string): Promise<IGBInstance> { public async deployBot(localPath: string): Promise<IGBInstance> {
const packageType = Path.extname(localPath); const packageType = Path.extname(localPath);
const packageName = Path.basename(localPath); const packageName = Path.basename(localPath);
const instance = await this.importer.importIfNotExistsBotPackage( const instance = await this.importer.importIfNotExistsBotPackage(null,
packageName, packageName,
localPath localPath
); );
return instance; 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); const packageType = Path.extname(localPath);
switch (packageType) { switch (packageType) {

View file

@ -50,41 +50,29 @@ export class GBImporter {
this.core = core; this.core = core;
} }
public async importIfNotExistsBotPackage( public async importIfNotExistsBotPackage(botId: string, packageName: string, localPath: string) {
packageName: string, const packageJson = JSON.parse(fs.readFileSync(UrlJoin(localPath, 'package.json'), 'utf8'));
localPath: string) { if (!botId) {
botId = packageJson.botId;
const packageJson = JSON.parse( }
fs.readFileSync(UrlJoin(localPath, 'package.json'), 'utf8')
);
const botId = packageJson.botId;
const instance = await this.core.loadInstance(botId); const instance = await this.core.loadInstance(botId);
if (instance) { if (instance) {
return instance; return instance;
} else { } else {
return await this.createInstanceInternal(packageName, localPath, packageJson); return await this.createInstanceInternal(botId, packageName, localPath, packageJson);
} }
} }
private async createInstanceInternal( private async createInstanceInternal(botId: string, packageName: string, localPath: string, packageJson: any) {
packageName: string, const settings = JSON.parse(fs.readFileSync(UrlJoin(localPath, 'settings.json'), 'utf8'));
localPath: string, const servicesJson = JSON.parse(fs.readFileSync(UrlJoin(localPath, 'services.json'), 'utf8'));
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) => { if (botId){
const service = new SecService(); packageJson.botId = botId;
// TODO: service.importSecurityFile(localPath, instance) }
Promise.resolve(instance); return GuaribasInstance.create(packageJson);
});
} }
} }

View file

@ -110,7 +110,8 @@ export class GBMinService {
public async buildMin( public async buildMin(
server: any, server: any,
appPackages: IGBPackage[], appPackages: IGBPackage[],
instances: GuaribasInstance[] instances: GuaribasInstance[],
deployer: GBDeployer
): Promise<GBMinInstance> { ): Promise<GBMinInstance> {
// Serves default UI on root address '/'. // Serves default UI on root address '/'.
@ -169,6 +170,11 @@ export class GBMinService {
instance instance
); );
// Install default VBA module.
deployer.deployPackageFromLocalPath(min, 'packages/default.gbdialog');
// Call the loadBot context.activity for all packages. // Call the loadBot context.activity for all packages.
this.invokeLoadBot(appPackages, min, server); this.invokeLoadBot(appPackages, min, server);

View file

@ -33,8 +33,7 @@
'use strict'; 'use strict';
import { IGBCoreService, IGBInstance } from 'botlib'; import { IGBCoreService, IGBInstance } from 'botlib';
import { GBError } from 'botlib'; import { GBMinInstance } from 'botlib';
import { IGBPackage } from 'botlib';
const logger = require('../../../src/logger'); const logger = require('../../../src/logger');
import { BotAdapter } from 'botbuilder'; import { BotAdapter } from 'botbuilder';
import { WaterfallDialog } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
@ -57,18 +56,20 @@ export class GBVMService implements IGBCoreService {
public async loadJS( public async loadJS(
filename: string, filename: string,
min: IGBInstance, min: GBMinInstance,
core: IGBCoreService, core: IGBCoreService,
deployer: GBDeployer, deployer: GBDeployer,
localPath: string localPath: string
): Promise<void> { ): Promise<void> {
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 sandbox: DialogClass = new DialogClass(min);
const context = vm.createContext(sandbox); const context = vm.createContext(sandbox);
this.script.runInContext(code, context); vm.runInContext(code, context);
console.log(util.inspect(sandbox)); console.log(util.inspect(sandbox));
sandbox['chat'](sandbox);
await deployer.deployScriptToStorage(min.instanceId, filename); await deployer.deployScriptToStorage(min.instanceId, filename);
logger.info(`[GBVMService] Finished loading of ${filename}`); logger.info(`[GBVMService] Finished loading of ${filename}`);

View file

@ -1,4 +1,6 @@
export function chat() {
function chat(bot) {
//**************************************************************************** //****************************************************************************
// ( )_ _ // ( )_ _
// _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ // _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _
@ -31,11 +33,13 @@ export function chat() {
// //
//**************************************************************************** //****************************************************************************
bot.talk('Qual seu e-mail?');
main = () => { main = () => {
bot.addFunction(PegaEmail); bot.addFunction(PegaEmail);
PegaEmail = bot => { PegaEmail = bot => {
bot.say('Qual seu e-mail?'); bot.talk('Qual seu e-mail?');
email = bot.expectEmail; email = bot.expectEmail;
bot.post('/restservice', email); bot.post('/restservice', email);
}; };

View file

@ -59,10 +59,10 @@ export class AskDialog extends IGBDialog {
min.dialogs.add( min.dialogs.add(
new WaterfallDialog('/answerEvent', [ new WaterfallDialog('/answerEvent', [
async step => { async step => {
if (step.options && step.options.questionId) { if (step.options && step.options['questionId']) {
const question = await service.getQuestionById( const question = await service.getQuestionById(
min.instance.instanceId, min.instance.instanceId,
step.options.questionId step.options['questionId']
); );
const answer = await service.getAnswerById( const answer = await service.getAnswerById(
min.instance.instanceId, min.instance.instanceId,
@ -84,7 +84,7 @@ export class AskDialog extends IGBDialog {
new WaterfallDialog('/answer', [ new WaterfallDialog('/answer', [
async step => { async step => {
const user = await min.userProfile.get(step.context, {}); const user = await min.userProfile.get(step.context, {});
let text = step.options.query; let text = step.options['query'];
if (!text) { if (!text) {
throw new Error(`/answer being called with no args query 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. // Handle extra text from FAQ.
if (step.options && step.options.query) { if (step.options && step.options['query']) {
text = step.options.query; text = step.options['query'];
} else if (step.options && step.options.fromFaq) { } else if (step.options && step.options['fromFaq']) {
await step.context.sendActivity(Messages[locale].going_answer); await step.context.sendActivity(Messages[locale].going_answer);
} }
@ -212,9 +212,9 @@ export class AskDialog extends IGBDialog {
// Three forms of asking. // Three forms of asking.
if (step.options && step.options.firstTime) { if (step.options && step.options['firstTime']) {
text = Messages[locale].ask_first_time; 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; text = Messages[locale].anything_else;
} else if (user.subjects.length > 0) { } else if (user.subjects.length > 0) {
text = Messages[locale].which_question; text = Messages[locale].which_question;

View file

@ -63,7 +63,7 @@ export class MenuDialog extends IGBDialog {
const locale = step.context.activity.locale; const locale = step.context.activity.locale;
let rootSubjectId = null; let rootSubjectId = null;
if (step.options && step.options.data) { if (step.options && step.options['data']) {
const subject = step.result.data; const subject = step.result.data;
// If there is a shortcut specified as subject destination, go there. // If there is a shortcut specified as subject destination, go there.

View file

@ -103,24 +103,32 @@ export class GBServer {
const conversationalService: GBConversationalService = new GBConversationalService(core); const conversationalService: GBConversationalService = new GBConversationalService(core);
core.ensureAdminIsSecured(); core.ensureAdminIsSecured();
const bootInstance = await core.createBootInstance(core, azureDeployer, proxyAddress); let bootInstance: IGBInstance = null;
await core.checkStorage(azureDeployer); try {
await core.initStorage();
} catch (error) {
bootInstance = await core.createBootInstance(core, azureDeployer, proxyAddress);
await core.initStorage();
}
await core.loadSysPackages(core); await core.loadSysPackages(core);
await core.checkStorage(azureDeployer);
await deployer.deployPackages(core, server, appPackages); await deployer.deployPackages(core, server, appPackages);
logger.info(`Publishing instances...`); 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); const fullInstance = Object.assign(packageInstance, bootInstance);
await core.saveInstance(fullInstance); await core.saveInstance(fullInstance);
let instances: GuaribasInstance[] = await core.loadAllInstances(core, azureDeployer, proxyAddress); let instances: GuaribasInstance[] = await core.loadAllInstances(core, azureDeployer, proxyAddress);
instances = await core.ensureInstances(instances, bootInstance, core); 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); 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...`); logger.info(`The Bot Server is in RUNNING mode...`);
core.openBrowserInDevelopment(); core.openBrowserInDevelopment();