fix(core): Bot boot logic being fixed.
This commit is contained in:
parent
c1db8be0c0
commit
1761e06061
23 changed files with 461 additions and 493 deletions
|
@ -1,8 +1,9 @@
|
|||
{
|
||||
"trailingComma": "all",
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"printWidth": 80,
|
||||
"printWidth": 120,
|
||||
"arrowParens": "avoid",
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
|
||||
}
|
34
package-lock.json
generated
34
package-lock.json
generated
|
@ -2966,9 +2966,9 @@
|
|||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
|
||||
"integrity": "sha1-G+CQjgVKdRdUVJwnBInBUF1KsVo="
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.18.3",
|
||||
|
@ -7105,13 +7105,11 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -7124,18 +7122,15 @@
|
|||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -7238,8 +7233,7 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -7249,7 +7243,6 @@
|
|||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -7262,20 +7255,17 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -7292,7 +7282,6 @@
|
|||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -7365,8 +7354,7 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -7376,7 +7364,6 @@
|
|||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -7482,7 +7469,6 @@
|
|||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
"azure-arm-search": "^1.3.0-preview",
|
||||
"azure-arm-sql": "5.6.0",
|
||||
"azure-arm-website": "5.7.0",
|
||||
"bluebird": "^3.5.3",
|
||||
"body-parser": "1.18.3",
|
||||
"botbuilder": "^4.1.5",
|
||||
"botbuilder-ai": "^4.1.5",
|
||||
|
|
|
@ -63,11 +63,11 @@ export class AdminDialog extends IGBDialog {
|
|||
);
|
||||
}
|
||||
|
||||
public static async deployPackageCommand(text: string, deployer: GBDeployer) {
|
||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
||||
const packageName = text.split(' ')[1];
|
||||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||
await deployer.deployPackageFromLocalPath(
|
||||
UrlJoin(additionalPath, packageName)
|
||||
await deployer.deployPackageFromLocalPath(min,
|
||||
UrlJoin(additionalPath, packageName)
|
||||
);
|
||||
}
|
||||
/**
|
||||
|
@ -119,11 +119,11 @@ export class AdminDialog extends IGBDialog {
|
|||
await AdminDialog.createFarmCommand(text, deployer);
|
||||
await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'deployPackage') {
|
||||
await AdminDialog.deployPackageCommand(text, deployer);
|
||||
await AdminDialog.deployPackageCommand(min, text, deployer);
|
||||
await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'redeployPackage') {
|
||||
await AdminDialog.undeployPackageCommand(text, min);
|
||||
await AdminDialog.deployPackageCommand(text, deployer);
|
||||
await AdminDialog.deployPackageCommand(min, text, deployer);
|
||||
await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'undeployPackage') {
|
||||
await AdminDialog.undeployPackageCommand(text, min);
|
||||
|
|
12
packages/boot.gbot/package.json
Normal file
12
packages/boot.gbot/package.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"version": "1.0.0",
|
||||
"theme": "default.gbtheme",
|
||||
"ui": "default.gbui",
|
||||
"kb": "default.gbkb",
|
||||
"title": "Default General Bot",
|
||||
"description": "Default General Bot",
|
||||
"whoAmIVideo": "TODO.mp4",
|
||||
"author": "pragmatismo.io",
|
||||
"license": "AGPL",
|
||||
"engineName": "guaribas-1.0.0"
|
||||
}
|
3
packages/boot.gbot/security.json
Normal file
3
packages/boot.gbot/security.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"groups": [{}]
|
||||
}
|
2
packages/boot.gbot/services.json
Normal file
2
packages/boot.gbot/services.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
6
packages/boot.gbot/settings.json
Normal file
6
packages/boot.gbot/settings.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"enabledAdmin": "true",
|
||||
"searchScore": ".15",
|
||||
"nlpScore": ".15",
|
||||
"nlpVsSearch": ".4"
|
||||
}
|
|
@ -46,7 +46,7 @@ export class DialogClass {
|
|||
this.min = min;
|
||||
}
|
||||
|
||||
public async expectMessage(text: string): Promise<any> {
|
||||
public async hear(text: string): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.min.dialogs.add(
|
||||
new WaterfallDialog('/vmExpect', [
|
||||
|
@ -63,7 +63,11 @@ export class DialogClass {
|
|||
});
|
||||
}
|
||||
|
||||
public sendMessage(text: string) {
|
||||
public post(url: string, data) {
|
||||
|
||||
}
|
||||
|
||||
public talk(text: string) {
|
||||
this.min.dialogs.add(
|
||||
new WaterfallDialog('/vmSend', [
|
||||
async step => {
|
||||
|
|
|
@ -31,18 +31,15 @@
|
|||
\*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @fileoverview General Bots server core.
|
||||
* @fileoverview Conversation handling and external service calls.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const logger = require('../../../src/logger');
|
||||
|
||||
import { any } from 'bluebird';
|
||||
import { MessageFactory } from 'botbuilder';
|
||||
import { LuisRecognizer } from 'botbuilder-ai';
|
||||
import { IGBConversationalService } from 'botlib';
|
||||
import { GBMinInstance } from 'botlib';
|
||||
import { GBMinInstance, IGBConversationalService } from 'botlib';
|
||||
import { AzureText } from 'pragmatismo-io-framework';
|
||||
import { Messages } from '../strings';
|
||||
import { GBCoreService } from './GBCoreService';
|
||||
|
@ -70,33 +67,27 @@ export class GBConversationalService implements IGBConversationalService {
|
|||
msg.value = value;
|
||||
msg.type = 'event';
|
||||
msg.name = name;
|
||||
|
||||
return step.context.sendActivity(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public async sendSms(
|
||||
min: GBMinInstance,
|
||||
mobile: string,
|
||||
text: string
|
||||
): Promise<any> {
|
||||
return new Promise((resolve: any, reject: any): any => {
|
||||
const nexmo = new Nexmo({
|
||||
apiKey: min.instance.smsKey,
|
||||
apiSecret: min.instance.smsSecret
|
||||
});
|
||||
nexmo.message.sendSms(
|
||||
min.instance.smsServiceNumber,
|
||||
mobile,
|
||||
text,
|
||||
(err, data) => {
|
||||
public async sendSms(min: GBMinInstance, mobile: string, text: string): Promise<any> {
|
||||
return new Promise(
|
||||
(resolve: any, reject: any): any => {
|
||||
const nexmo = new Nexmo({
|
||||
apiKey: min.instance.smsKey,
|
||||
apiSecret: min.instance.smsSecret
|
||||
});
|
||||
nexmo.message.sendSms(min.instance.smsServiceNumber, mobile, text, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public async routeNLP(step: any, min: GBMinInstance, text: string): Promise<boolean> {
|
||||
|
@ -112,15 +103,17 @@ export class GBConversationalService implements IGBConversationalService {
|
|||
try {
|
||||
nlp = await model.recognize(step.context);
|
||||
} catch (error) {
|
||||
if (error.statusCode == 404) {
|
||||
logger.warn ('NLP application still not publish and there are no other options for answering.');
|
||||
if (error.statusCode === 404) {
|
||||
logger.warn('NLP application still not publish and there are no other options for answering.');
|
||||
|
||||
return Promise.resolve(false);
|
||||
} else {
|
||||
const msg = `Error calling NLP server, check if you have a published model and assigned keys on the service. Error: ${
|
||||
error.statusCode ? error.statusCode : ''
|
||||
} ${error.message}`;
|
||||
return Promise.reject(new Error(msg)); }
|
||||
const msg = `Error calling NLP, check if you have a published model and assigned keys. Error: ${
|
||||
error.statusCode ? error.statusCode : ''
|
||||
} ${error.message}`;
|
||||
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
}
|
||||
|
||||
// Resolves intents returned from LUIS.
|
||||
|
@ -128,37 +121,31 @@ export class GBConversationalService implements IGBConversationalService {
|
|||
const topIntent = LuisRecognizer.topIntent(nlp);
|
||||
if (topIntent) {
|
||||
const intent = topIntent;
|
||||
const entity =
|
||||
nlp.entities && nlp.entities.length > 0
|
||||
? nlp.entities[0].entity.toUpperCase()
|
||||
: null;
|
||||
const entity = nlp.entities && nlp.entities.length > 0 ? nlp.entities[0].entity.toUpperCase() : null;
|
||||
|
||||
if (intent === 'None') {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
logger.info('NLP called:' + intent + ', ' + entity);
|
||||
logger.info(`NLP called: ${intent}, ${entity}`);
|
||||
|
||||
try {
|
||||
await step.replace('/' + intent, nlp.entities);
|
||||
await step.replace(`/${intent}`, nlp.entities);
|
||||
|
||||
return Promise.resolve(true);
|
||||
} catch (error) {
|
||||
const msg = `Error finding dialog associated to NLP event: ${intent}: ${
|
||||
error.message
|
||||
}`;
|
||||
const msg = `Error finding dialog associated to NLP event: ${intent}: ${error.message}`;
|
||||
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
public async checkLanguage(step, min, text) {
|
||||
const locale = await AzureText.getLocale(
|
||||
min.instance.textAnalyticsKey,
|
||||
min.instance.textAnalyticsEndpoint,
|
||||
text
|
||||
);
|
||||
if (locale != step.context.activity.locale.split('-')[0]) {
|
||||
const locale = await AzureText.getLocale(min.instance.textAnalyticsKey, min.instance.textAnalyticsEndpoint, text);
|
||||
if (locale !== step.context.activity.locale.split('-')[0]) {
|
||||
switch (locale) {
|
||||
case 'pt':
|
||||
step.context.activity.locale = 'pt-BR';
|
||||
|
|
|
@ -39,17 +39,18 @@
|
|||
import { IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||
import * as fs from 'fs';
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { GBAdminPackage } from '../../admin.gbapp/index';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { GBAnalyticsPackage } from '../../analytics.gblib';
|
||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||
import { GBCorePackage } from '../../core.gbapp';
|
||||
import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp';
|
||||
import { GBKBPackage } from '../../kb.gbapp';
|
||||
import { GBSecurityPackage } from '../../security.gblib';
|
||||
import { GBWhatsappPackage } from '../../whatsapp.gblib/index';
|
||||
import { GuaribasInstance } from '../models/GBModel';
|
||||
import { GBConfigService } from './GBConfigService';
|
||||
import { AzureDeployerService } from 'packages/azuredeployer.gbapp/services/AzureDeployerService';
|
||||
import { GBAnalyticsPackage } from 'packages/analytics.gblib';
|
||||
import { GBAdminPackage } from 'packages/admin.gbapp/index';
|
||||
import { GBCorePackage } from 'packages/core.gbapp';
|
||||
import { GBCustomerSatisfactionPackage } from 'packages/customer-satisfaction.gbapp';
|
||||
import { GBKBPackage } from 'packages/kb.gbapp';
|
||||
import { GBSecurityPackage } from 'packages/security.gblib';
|
||||
import { GBWhatsappPackage } from 'packages/whatsapp.gblib/index';
|
||||
import { GBImporter } from './GBImporterService';
|
||||
|
||||
const logger = require('../../../src/logger');
|
||||
const opn = require('opn');
|
||||
|
@ -76,11 +77,7 @@ export class GBCoreService implements IGBCoreService {
|
|||
/**
|
||||
* Custom create table query.
|
||||
*/
|
||||
private createTableQuery: (
|
||||
tableName: string,
|
||||
attributes: any,
|
||||
options: any,
|
||||
) => string;
|
||||
private createTableQuery: (tableName: string, attributes: any, options: any) => string;
|
||||
|
||||
/**
|
||||
* Custom change column query.
|
||||
|
@ -102,78 +99,79 @@ export class GBCoreService implements IGBCoreService {
|
|||
/**
|
||||
* Gets database config and connect to storage.
|
||||
*/
|
||||
public async initDatabase(): Promise<any> {
|
||||
return new Promise(
|
||||
(resolve: any, reject: any): any => {
|
||||
try {
|
||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||
|
||||
let host: string | undefined;
|
||||
let database: string | undefined;
|
||||
let username: string | undefined;
|
||||
let password: string | undefined;
|
||||
let storage: string | undefined;
|
||||
public async initStorage(): Promise<any> {
|
||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||
|
||||
if (this.dialect === 'mssql') {
|
||||
host = GBConfigService.get('STORAGE_SERVER');
|
||||
database = GBConfigService.get('STORAGE_NAME');
|
||||
username = GBConfigService.get('STORAGE_USERNAME');
|
||||
password = GBConfigService.get('STORAGE_PASSWORD');
|
||||
} else if (this.dialect === 'sqlite') {
|
||||
storage = GBConfigService.get('STORAGE_STORAGE');
|
||||
} else {
|
||||
reject(`Unknown dialect: ${this.dialect}.`);
|
||||
let host: string | undefined;
|
||||
let database: string | undefined;
|
||||
let username: string | undefined;
|
||||
let password: string | undefined;
|
||||
let storage: string | undefined;
|
||||
|
||||
if (this.dialect === 'mssql') {
|
||||
host = GBConfigService.get('STORAGE_SERVER');
|
||||
database = GBConfigService.get('STORAGE_NAME');
|
||||
username = GBConfigService.get('STORAGE_USERNAME');
|
||||
password = GBConfigService.get('STORAGE_PASSWORD');
|
||||
} else if (this.dialect === 'sqlite') {
|
||||
storage = GBConfigService.get('STORAGE_STORAGE');
|
||||
} else {
|
||||
throw new Error(`Unknown dialect: ${this.dialect}.`);
|
||||
}
|
||||
|
||||
const logging: any =
|
||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||
? (str: string): void => {
|
||||
logger.info(str);
|
||||
}
|
||||
: false;
|
||||
|
||||
const logging: any =
|
||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||
? (str: string): void => {
|
||||
logger.info(str);
|
||||
}
|
||||
: false;
|
||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||
|
||||
const encrypt: boolean =
|
||||
GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||
|
||||
this.sequelize = new Sequelize({
|
||||
host: host,
|
||||
database: database,
|
||||
username: username,
|
||||
password: password,
|
||||
logging: logging,
|
||||
operatorsAliases: false,
|
||||
dialect: this.dialect,
|
||||
storage: storage,
|
||||
dialectOptions: {
|
||||
encrypt: encrypt,
|
||||
},
|
||||
pool: {
|
||||
max: 32,
|
||||
min: 8,
|
||||
idle: 40000,
|
||||
evict: 40000,
|
||||
acquire: 40000,
|
||||
},
|
||||
});
|
||||
|
||||
if (this.dialect === 'mssql') {
|
||||
this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator;
|
||||
this.createTableQuery = this.queryGenerator.createTableQuery;
|
||||
this.queryGenerator.createTableQuery = (
|
||||
tableName,
|
||||
attributes,
|
||||
options,
|
||||
) => this.createTableQueryOverride(tableName, attributes, options);
|
||||
this.changeColumnQuery = this.queryGenerator.changeColumnQuery;
|
||||
this.queryGenerator.changeColumnQuery = (tableName, attributes) =>
|
||||
this.changeColumnQueryOverride(tableName, attributes);
|
||||
}
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
this.sequelize = new Sequelize({
|
||||
host: host,
|
||||
database: database,
|
||||
username: username,
|
||||
password: password,
|
||||
logging: logging,
|
||||
operatorsAliases: false,
|
||||
dialect: this.dialect,
|
||||
storage: storage,
|
||||
dialectOptions: {
|
||||
encrypt: encrypt
|
||||
},
|
||||
);
|
||||
pool: {
|
||||
max: 32,
|
||||
min: 8,
|
||||
idle: 40000,
|
||||
evict: 40000,
|
||||
acquire: 40000
|
||||
}
|
||||
});
|
||||
|
||||
if (this.dialect === 'mssql') {
|
||||
this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator;
|
||||
this.createTableQuery = this.queryGenerator.createTableQuery;
|
||||
this.queryGenerator.createTableQuery = (tableName, attributes, options) =>
|
||||
this.createTableQueryOverride(tableName, attributes, options);
|
||||
this.changeColumnQuery = this.queryGenerator.changeColumnQuery;
|
||||
this.queryGenerator.changeColumnQuery = (tableName, attributes) =>
|
||||
this.changeColumnQueryOverride(tableName, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
public async checkStorage(azureDeployer: AzureDeployerService) {
|
||||
try {
|
||||
await this.sequelize.authenticate();
|
||||
} catch (error) {
|
||||
logger.info('Opening storage firewall on infrastructure...');
|
||||
if (error.parent.code === 'ELOGIN') {
|
||||
await this.openStorageFrontier(azureDeployer);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async syncDatabaseStructure() {
|
||||
|
@ -181,9 +179,10 @@ export class GBCoreService implements IGBCoreService {
|
|||
const alter = GBConfigService.get('STORAGE_SYNC_ALTER') === 'true';
|
||||
const force = GBConfigService.get('STORAGE_SYNC_FORCE') === 'true';
|
||||
logger.info('Syncing database...');
|
||||
|
||||
return this.sequelize.sync({
|
||||
alter: alter,
|
||||
force: force,
|
||||
force: force
|
||||
});
|
||||
} else {
|
||||
const msg = 'Database synchronization is disabled.';
|
||||
|
@ -203,6 +202,7 @@ export class GBCoreService implements IGBCoreService {
|
|||
*/
|
||||
public async loadInstanceById(instanceId: string): Promise<IGBInstance> {
|
||||
const options = { where: { instanceId: instanceId } };
|
||||
|
||||
return GuaribasInstance.findOne(options);
|
||||
}
|
||||
|
||||
|
@ -211,63 +211,182 @@ export class GBCoreService implements IGBCoreService {
|
|||
*/
|
||||
public async loadInstance(botId: string): Promise<IGBInstance> {
|
||||
const options = { where: {} };
|
||||
options.where = { botId: botId };
|
||||
|
||||
if (botId !== '[default]') {
|
||||
options.where = { botId: botId };
|
||||
}
|
||||
|
||||
return GuaribasInstance.findOne(options);
|
||||
return await GuaribasInstance.findOne(options);
|
||||
}
|
||||
|
||||
public async writeEnv(instance: IGBInstance) {
|
||||
const env =
|
||||
`ADDITIONAL_DEPLOY_PATH=\n` +
|
||||
`ADMIN_PASS=${instance.adminPass}\n` +
|
||||
`CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}\n` +
|
||||
`CLOUD_LOCATION=${instance.cloudLocation}\n` +
|
||||
`CLOUD_GROUP=${instance.botId}\n` +
|
||||
`CLOUD_USERNAME=${instance.cloudUsername}\n` +
|
||||
`CLOUD_PASSWORD=${instance.cloudPassword}\n` +
|
||||
`MARKETPLACE_ID=${instance.marketplaceId}\n` +
|
||||
`MARKETPLACE_SECRET=${instance.marketplacePassword}\n` +
|
||||
`NLP_AUTHORING_KEY=${instance.nlpAuthoringKey}\n` +
|
||||
`STORAGE_DIALECT=${instance.storageDialect}\n` +
|
||||
`STORAGE_SERVER=${instance.storageServer}.database.windows.net\n` +
|
||||
`STORAGE_NAME=${instance.storageName}\n` +
|
||||
`STORAGE_USERNAME=${instance.storageUsername}\n` +
|
||||
`STORAGE_PASSWORD=${instance.storagePassword}\n` +
|
||||
`STORAGE_SYNC=true\n`;
|
||||
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`;
|
||||
|
||||
fs.writeFileSync('.env', env);
|
||||
}
|
||||
|
||||
public async ensureProxy(port): Promise<string> {
|
||||
let proxyAddress: string;
|
||||
const ngrok = require('ngrok');
|
||||
|
||||
return await ngrok.connect({ port: port });
|
||||
}
|
||||
|
||||
public async saveInstance(fullInstance: any) {
|
||||
const options = { where: {} };
|
||||
options.where = { botId: fullInstance.botId };
|
||||
let instance = await GuaribasInstance.findOne(options);
|
||||
// tslint:disable-next-line:prefer-object-spread
|
||||
instance = Object.assign(instance, fullInstance);
|
||||
|
||||
return await instance.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all bot instances from object storage, if it's formatted.
|
||||
*
|
||||
* @param core
|
||||
* @param azureDeployer
|
||||
* @param proxyAddress
|
||||
*/
|
||||
public async loadAllInstances(core: GBCoreService, azureDeployer: AzureDeployerService, proxyAddress: string) {
|
||||
logger.info(`Loading instances from storage...`);
|
||||
let instances: GuaribasInstance[];
|
||||
try {
|
||||
instances = await core.loadInstances();
|
||||
const instance = instances[0];
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
logger.info(`Updating bot endpoint to local reverse proxy (ngrok)...`);
|
||||
await azureDeployer.updateBotProxy(
|
||||
instance.botId,
|
||||
instance.botId,
|
||||
`${proxyAddress}/api/messages/${instance.botId}`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// Check if storage is empty and needs formatting.
|
||||
const isInvalidObject = error.parent.number == 208 || error.parent.errno == 1; // MSSQL or SQLITE.
|
||||
if (isInvalidObject) {
|
||||
if (GBConfigService.get('STORAGE_SYNC') != 'true') {
|
||||
throw new Error(
|
||||
`Operating storage is out of sync or there is a storage connection error.
|
||||
Try setting STORAGE_SYNC to true in .env file. Error: ${error.message}.`
|
||||
);
|
||||
} else {
|
||||
logger.info(`Storage is empty. After collecting storage structure from all .gbapps it will get synced.`);
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Cannot connect to operating storage: ${error.message}.`);
|
||||
}
|
||||
}
|
||||
|
||||
return instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* If instances is undefined here it's because storage has been formatted.
|
||||
* Load all instances from .gbot found on deploy package directory.
|
||||
* @param instances
|
||||
* @param bootInstance
|
||||
* @param core
|
||||
*/
|
||||
public async ensureInstances(instances: GuaribasInstance[], bootInstance: any, core: GBCoreService) {
|
||||
if (!instances) {
|
||||
const saveInstance = new GuaribasInstance(bootInstance);
|
||||
await saveInstance.save();
|
||||
instances = await core.loadInstances();
|
||||
}
|
||||
|
||||
return instances;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
[
|
||||
GBAdminPackage,
|
||||
GBAnalyticsPackage,
|
||||
GBCorePackage,
|
||||
GBSecurityPackage,
|
||||
GBKBPackage,
|
||||
GBCustomerSatisfactionPackage,
|
||||
GBWhatsappPackage
|
||||
].forEach(e => {
|
||||
logger.info(`Loading sys package: ${e.name}...`);
|
||||
const p = Object.create(e.prototype) as IGBPackage;
|
||||
p.loadPackage(core, core.sequelize);
|
||||
});
|
||||
}
|
||||
|
||||
public ensureAdminIsSecured() {
|
||||
const password = GBConfigService.get('ADMIN_PASS');
|
||||
if (!GBAdminService.StrongRegex.test(password)) {
|
||||
throw new Error(
|
||||
'Please, define a really strong password in ADMIN_PASS environment variable before running the server.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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.'
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
core.writeEnv(instance);
|
||||
logger.info(`File .env written, starting General Bots...`);
|
||||
GBConfigService.init();
|
||||
await core.initStorage();
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public openBrowserInDevelopment() {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
opn('http://localhost:4242');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL:
|
||||
*
|
||||
* // let sql: string = '' +
|
||||
* // 'IF OBJECT_ID(\'[UserGroup]\', \'U\') IS NULL\n' +
|
||||
* // 'CREATE TABLE [UserGroup] (\n' +
|
||||
* // ' [id] INTEGER NOT NULL IDENTITY(1,1),\n' +
|
||||
* // ' [userId] INTEGER NULL,\n' +
|
||||
* // ' [groupId] INTEGER NULL,\n' +
|
||||
* // ' [instanceId] INTEGER NULL,\n' +
|
||||
* // ' PRIMARY KEY ([id1], [id2]),\n' +
|
||||
* // ' FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,\n' +
|
||||
* // ' FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId1]) ON DELETE NO ACTION,\n' +
|
||||
* // 'IF OBJECT_ID(\'[UserGroup]\', \'U\') IS NULL' +
|
||||
* // 'CREATE TABLE [UserGroup] (' +
|
||||
* // ' [id] INTEGER NOT NULL IDENTITY(1,1),' +
|
||||
* // ' [userId] INTEGER NULL,' +
|
||||
* // ' [groupId] INTEGER NULL,' +
|
||||
* // ' [instanceId] INTEGER NULL,' +
|
||||
* // ' PRIMARY KEY ([id1], [id2]),' +
|
||||
* // ' FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,' +
|
||||
* // ' FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId1]) ON DELETE NO ACTION,' +
|
||||
* // ' FOREIGN KEY ([instanceId]) REFERENCES [Instance] ([instanceId]) ON DELETE NO ACTION)'
|
||||
*/
|
||||
private createTableQueryOverride(tableName, attributes, options): string {
|
||||
let sql: string = this.createTableQuery.apply(this.queryGenerator, [
|
||||
tableName,
|
||||
attributes,
|
||||
options,
|
||||
]);
|
||||
let sql: string = this.createTableQuery.apply(this.queryGenerator, [tableName, attributes, options]);
|
||||
const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/;
|
||||
const matches = re1.exec(sql);
|
||||
if (matches) {
|
||||
|
@ -277,7 +396,7 @@ export class GBCoreService implements IGBCoreService {
|
|||
re2,
|
||||
(match: string, ...args: any[]): string => {
|
||||
return 'CONSTRAINT [' + table + '_pk] ' + match;
|
||||
},
|
||||
}
|
||||
);
|
||||
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
|
||||
const re4 = /\[([^\]]*)\]/g;
|
||||
|
@ -292,7 +411,7 @@ export class GBCoreService implements IGBCoreService {
|
|||
matches = re4.exec(fkcols);
|
||||
}
|
||||
return 'CONSTRAINT [' + fkname + '_fk] FOREIGN KEY (' + fkcols + ')';
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
return sql;
|
||||
|
@ -301,16 +420,13 @@ export class GBCoreService implements IGBCoreService {
|
|||
/**
|
||||
* SQL:
|
||||
* let sql = '' +
|
||||
* 'ALTER TABLE [UserGroup]\n' +
|
||||
* ' ADD CONSTRAINT [invalid1] FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,\n' +
|
||||
* ' CONSTRAINT [invalid2] FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId2]) ON DELETE NO ACTION, \n' +
|
||||
* ' CONSTRAINT [invalid3] FOREIGN KEY ([instanceId1]) REFERENCES [Instance] ([instanceId1]) ON DELETE NO ACTION\n'
|
||||
* 'ALTER TABLE [UserGroup]' +
|
||||
* ' ADD CONSTRAINT [invalid1] FOREIGN KEY ([userId1], [userId2], [userId3]) REFERENCES [User] ([userId1], [userId2], [userId3]) ON DELETE NO ACTION,' +
|
||||
* ' CONSTRAINT [invalid2] FOREIGN KEY ([groupId1], [groupId2]) REFERENCES [Group] ([groupId1], [groupId2]) ON DELETE NO ACTION, ' +
|
||||
* ' CONSTRAINT [invalid3] FOREIGN KEY ([instanceId1]) REFERENCES [Instance] ([instanceId1]) ON DELETE NO ACTION'
|
||||
*/
|
||||
private changeColumnQueryOverride(tableName, attributes): string {
|
||||
let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [
|
||||
tableName,
|
||||
attributes,
|
||||
]);
|
||||
let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [tableName, attributes]);
|
||||
const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/;
|
||||
const matches = re1.exec(sql);
|
||||
if (matches) {
|
||||
|
@ -327,159 +443,21 @@ export class GBCoreService implements IGBCoreService {
|
|||
fkname += '_' + matches[1];
|
||||
matches = re3.exec(fkcols);
|
||||
}
|
||||
return (
|
||||
(args[0] ? args[0] : '') +
|
||||
'CONSTRAINT [' +
|
||||
fkname +
|
||||
'_fk] FOREIGN KEY (' +
|
||||
fkcols +
|
||||
')'
|
||||
);
|
||||
},
|
||||
return (args[0] ? args[0] : '') + 'CONSTRAINT [' + fkname + '_fk] FOREIGN KEY (' + fkcols + ')';
|
||||
}
|
||||
);
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all bot instances from object storage, if it's formatted.
|
||||
* Opens storage firewall.
|
||||
*
|
||||
* @param core
|
||||
* @param azureDeployer
|
||||
* @param proxyAddress
|
||||
* @param azureDeployer Infrastructure Deployer instance.
|
||||
*/
|
||||
public async loadAllInstances(
|
||||
core: GBCoreService,
|
||||
azureDeployer: AzureDeployerService,
|
||||
proxyAddress: string,
|
||||
) {
|
||||
logger.info(`Loading instances from storage...`);
|
||||
let instances: GuaribasInstance[];
|
||||
try {
|
||||
instances = await core.loadInstances();
|
||||
const instance = instances[0];
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
logger.info(`Updating bot endpoint to local reverse proxy (ngrok)...`);
|
||||
await azureDeployer.updateBotProxy(
|
||||
instance.botId,
|
||||
instance.botId,
|
||||
`${proxyAddress}/api/messages/${instance.botId}`,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.parent.code === 'ELOGIN') {
|
||||
const group = GBConfigService.get('CLOUD_GROUP');
|
||||
const serverName = GBConfigService.get('STORAGE_SERVER').split(
|
||||
'.database.windows.net',
|
||||
)[0];
|
||||
await azureDeployer.openStorageFirewall(group, serverName);
|
||||
} else {
|
||||
// Check if storage is empty and needs formatting.
|
||||
const isInvalidObject =
|
||||
error.parent.number == 208 || error.parent.errno == 1; // MSSQL or SQLITE.
|
||||
if (isInvalidObject) {
|
||||
if (GBConfigService.get('STORAGE_SYNC') != 'true') {
|
||||
throw new Error(
|
||||
`Operating storage is out of sync or there is a storage connection error. Try setting STORAGE_SYNC to true in .env file. Error: ${
|
||||
error.message
|
||||
}.`,
|
||||
);
|
||||
} else {
|
||||
logger.info(
|
||||
`Storage is empty. After collecting storage structure from all .gbapps it will get synced.`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`Cannot connect to operating storage: ${error.message}.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instances;
|
||||
private async openStorageFrontier(deployer: AzureDeployerService) {
|
||||
const group = GBConfigService.get('CLOUD_GROUP');
|
||||
const serverName = GBConfigService.get('STORAGE_SERVER').split('.database.windows.net')[0];
|
||||
await deployer.openStorageFirewall(group, serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* If instances is undefined here it's because storage has been formatted.
|
||||
* Load all instances from .gbot found on deploy package directory.
|
||||
* @param instances
|
||||
* @param bootInstance
|
||||
* @param core
|
||||
*/
|
||||
public async ensureInstances(
|
||||
instances: GuaribasInstance[],
|
||||
bootInstance: any,
|
||||
core: GBCoreService,
|
||||
) {
|
||||
if (!instances) {
|
||||
const saveInstance = new GuaribasInstance(bootInstance);
|
||||
await saveInstance.save();
|
||||
instances = await core.loadInstances();
|
||||
}
|
||||
return instances;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
[
|
||||
GBAdminPackage,
|
||||
GBAnalyticsPackage,
|
||||
GBCorePackage,
|
||||
GBSecurityPackage,
|
||||
GBKBPackage,
|
||||
GBCustomerSatisfactionPackage,
|
||||
GBWhatsappPackage,
|
||||
].forEach(e => {
|
||||
logger.info(`Loading sys package: ${e.name}...`);
|
||||
const p = Object.create(e.prototype) as IGBPackage;
|
||||
p.loadPackage(core, core.sequelize);
|
||||
});
|
||||
}
|
||||
|
||||
public ensureAdminIsSecured() {
|
||||
const password = GBConfigService.get('ADMIN_PASS');
|
||||
if (!GBAdminService.StrongRegex.test(password)) {
|
||||
throw new Error(
|
||||
'Please, define a really strong password in ADMIN_PASS environment variable before running the server.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async createBootInstance(
|
||||
core: GBCoreService,
|
||||
azureDeployer: AzureDeployerService,
|
||||
proxyAddress: string,
|
||||
) {
|
||||
let bootInstance: IGBInstance;
|
||||
try {
|
||||
await core.initDatabase();
|
||||
} catch (error) {
|
||||
logger.info(
|
||||
`Deploying cognitive infrastructure (on the cloud / on premises)...`,
|
||||
);
|
||||
try {
|
||||
bootInstance = 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.',
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
core.writeEnv(bootInstance);
|
||||
logger.info(`File .env written, starting General Bots...`);
|
||||
GBConfigService.init();
|
||||
await core.initDatabase();
|
||||
}
|
||||
return bootInstance;
|
||||
}
|
||||
|
||||
public openBrowserInDevelopment() {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
opn('http://localhost:4242');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ export class GBDeployer {
|
|||
public deployPackages(
|
||||
core: IGBCoreService,
|
||||
server: any,
|
||||
appPackages: IGBPackage[],
|
||||
appPackages: IGBPackage[]
|
||||
) {
|
||||
const _this = this;
|
||||
return new Promise(
|
||||
|
@ -93,7 +93,6 @@ export class GBDeployer {
|
|||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||
let paths = [GBDeployer.deployFolder];
|
||||
if (additionalPath) {
|
||||
|
||||
paths = paths.concat(additionalPath.toLowerCase().split(';'));
|
||||
}
|
||||
const botPackages = new Array<string>();
|
||||
|
@ -124,7 +123,7 @@ export class GBDeployer {
|
|||
}
|
||||
|
||||
logger.info(
|
||||
`Starting looking for packages (.gbot, .gbtheme, .gbkb, .gbapp)...`,
|
||||
`Starting looking for packages (.gbot, .gbtheme, .gbkb, .gbapp)...`
|
||||
);
|
||||
paths.forEach(e => {
|
||||
logger.info(`Looking in: ${e}...`);
|
||||
|
@ -199,20 +198,22 @@ export class GBDeployer {
|
|||
server.use('/themes/' + filenameOnly, express.static(filename));
|
||||
logger.info(
|
||||
`Theme (.gbtheme) assets accessible at: ${'/themes/' +
|
||||
filenameOnly}.`,
|
||||
filenameOnly}.`
|
||||
);
|
||||
|
||||
/** Knowledge base for bots. */
|
||||
} else if (Path.extname(filename) === '.gbkb') {
|
||||
server.use(
|
||||
'/kb/' + filenameOnly + '/subjects',
|
||||
express.static(UrlJoin(filename, 'subjects')),
|
||||
express.static(UrlJoin(filename, 'subjects'))
|
||||
);
|
||||
logger.info(
|
||||
`KB (.gbkb) assets accessible at: ${'/kb/' + filenameOnly}.`,
|
||||
`KB (.gbkb) assets accessible at: ${'/kb/' + filenameOnly}.`
|
||||
);
|
||||
} else if (Path.extname(filename) === '.gbui') {
|
||||
// Already Handled
|
||||
} else if (Path.extname(filename) === '.gbdialog') {
|
||||
// Already Handled
|
||||
} else {
|
||||
/** Unknown package format. */
|
||||
const err = new Error(`Package type not handled: ${filename}.`);
|
||||
|
@ -231,7 +232,7 @@ export class GBDeployer {
|
|||
.done(function(result) {
|
||||
if (botPackages.length === 0) {
|
||||
logger.info(
|
||||
'No external packages to load, please use ADDITIONAL_DEPLOY_PATH to point to a .gbai package folder.',
|
||||
'No external packages to load, please use ADDITIONAL_DEPLOY_PATH to point to a .gbai package folder.'
|
||||
);
|
||||
} else {
|
||||
logger.info(`Package deployment done.`);
|
||||
|
@ -239,7 +240,7 @@ export class GBDeployer {
|
|||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -252,24 +253,22 @@ export class GBDeployer {
|
|||
const packageName = Path.basename(localPath);
|
||||
const instance = await this.importer.importIfNotExistsBotPackage(
|
||||
packageName,
|
||||
localPath,
|
||||
localPath
|
||||
);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public async deployPackageToStorage(
|
||||
instanceId: number,
|
||||
packageName: string,
|
||||
packageName: string
|
||||
): Promise<GuaribasPackage> {
|
||||
return GuaribasPackage.create({
|
||||
packageName: packageName,
|
||||
instanceId: instanceId,
|
||||
instanceId: instanceId
|
||||
});
|
||||
}
|
||||
|
||||
public deployScriptToStorage(instanceId: number, localPath: string) {
|
||||
|
||||
}
|
||||
public deployScriptToStorage(instanceId: number, localPath: string) {}
|
||||
|
||||
public deployTheme(localPath: string) {
|
||||
// DISABLED: Until completed, "/ui/public".
|
||||
|
@ -283,7 +282,7 @@ export class GBDeployer {
|
|||
// })
|
||||
}
|
||||
|
||||
public async deployPackageFromLocalPath(localPath: string) {
|
||||
public async deployPackageFromLocalPath(min: IGBInstance, localPath: string) {
|
||||
const packageType = Path.extname(localPath);
|
||||
|
||||
switch (packageType) {
|
||||
|
@ -303,7 +302,7 @@ export class GBDeployer {
|
|||
|
||||
case '.gbdialog':
|
||||
const vm = new GBVMService();
|
||||
return service.deployKb(this.core, this, localPath);
|
||||
return vm.loadJS(localPath, min, this.core, this, localPath);
|
||||
|
||||
default:
|
||||
const err = GBError.create(
|
||||
|
@ -316,7 +315,7 @@ export class GBDeployer {
|
|||
|
||||
public async undeployPackageFromLocalPath(
|
||||
instance: IGBInstance,
|
||||
localPath: string,
|
||||
localPath: string
|
||||
) {
|
||||
const packageType = Path.extname(localPath);
|
||||
const packageName = Path.basename(localPath);
|
||||
|
@ -339,9 +338,12 @@ export class GBDeployer {
|
|||
case '.gbui':
|
||||
break;
|
||||
|
||||
case '.gbdialog':
|
||||
break;
|
||||
|
||||
default:
|
||||
const err = GBError.create(
|
||||
`GuaribasBusinessError: Unknown package type: ${packageType}.`,
|
||||
`GuaribasBusinessError: Unknown package type: ${packageType}.`
|
||||
);
|
||||
Promise.reject(err);
|
||||
break;
|
||||
|
@ -353,11 +355,11 @@ export class GBDeployer {
|
|||
instance.searchKey,
|
||||
instance.searchHost,
|
||||
instance.searchIndex,
|
||||
instance.searchIndexer,
|
||||
instance.searchIndexer
|
||||
);
|
||||
|
||||
const connectionString = GBDeployer.getConnectionStringFromInstance(
|
||||
instance,
|
||||
instance
|
||||
);
|
||||
|
||||
const dsName = 'gb';
|
||||
|
@ -375,7 +377,7 @@ export class GBDeployer {
|
|||
dsName,
|
||||
'GuaribasQuestion',
|
||||
'azuresql',
|
||||
connectionString,
|
||||
connectionString
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -388,35 +390,17 @@ export class GBDeployer {
|
|||
}
|
||||
await search.createIndex(
|
||||
AzureDeployerService.getKBSearchSchema(instance.searchIndex),
|
||||
dsName,
|
||||
dsName
|
||||
);
|
||||
}
|
||||
|
||||
public async getPackageByName(
|
||||
instanceId: number,
|
||||
packageName: string,
|
||||
packageName: string
|
||||
): Promise<GuaribasPackage> {
|
||||
const where = { packageName: packageName, instanceId: instanceId };
|
||||
return GuaribasPackage.findOne({
|
||||
where: where,
|
||||
where: where
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Hot deploy processing.
|
||||
*
|
||||
*/
|
||||
public async scanBootPackage() {
|
||||
const deployFolder = 'packages';
|
||||
const bootPackage = GBConfigService.get('BOOT_PACKAGE');
|
||||
|
||||
if (bootPackage === 'none') {
|
||||
return Promise.resolve(true);
|
||||
} else {
|
||||
return this.deployPackageFromLocalPath(
|
||||
UrlJoin(deployFolder, bootPackage),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,14 +57,12 @@ export class GBImporter {
|
|||
const packageJson = JSON.parse(
|
||||
fs.readFileSync(UrlJoin(localPath, 'package.json'), 'utf8')
|
||||
);
|
||||
|
||||
const botId = packageJson.botId;
|
||||
|
||||
const instance = await this.core.loadInstance(botId);
|
||||
if (instance) {
|
||||
return Promise.resolve(instance);
|
||||
return instance;
|
||||
} else {
|
||||
return this.createInstanceInternal(packageName, localPath, packageJson);
|
||||
return await this.createInstanceInternal(packageName, localPath, packageJson);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +81,6 @@ export class GBImporter {
|
|||
packageJson = {...packageJson, ...settings, ...servicesJson};
|
||||
|
||||
GuaribasInstance.create(packageJson).then((instance: IGBInstance) => {
|
||||
|
||||
const service = new SecService();
|
||||
// TODO: service.importSecurityFile(localPath, instance)
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ export class GBMinService {
|
|||
core: IGBCoreService,
|
||||
conversationalService: IGBConversationalService,
|
||||
adminService: IGBAdminService,
|
||||
deployer: GBDeployer,
|
||||
deployer: GBDeployer
|
||||
) {
|
||||
this.core = core;
|
||||
this.conversationalService = conversationalService;
|
||||
|
@ -110,14 +110,14 @@ export class GBMinService {
|
|||
public async buildMin(
|
||||
server: any,
|
||||
appPackages: IGBPackage[],
|
||||
instances: GuaribasInstance[],
|
||||
instances: GuaribasInstance[]
|
||||
): Promise<GBMinInstance> {
|
||||
// Serves default UI on root address '/'.
|
||||
|
||||
const uiPackage = 'default.gbui';
|
||||
server.use(
|
||||
'/',
|
||||
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, 'build')),
|
||||
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, 'build'))
|
||||
);
|
||||
|
||||
Promise.all(
|
||||
|
@ -152,8 +152,8 @@ export class GBMinService {
|
|||
speechToken: speechToken,
|
||||
conversationId: webchatToken.conversationId,
|
||||
authenticatorTenant: instance.authenticatorTenant,
|
||||
authenticatorClientId: instance.authenticatorClientId,
|
||||
}),
|
||||
authenticatorClientId: instance.authenticatorClientId
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const error = `Instance not found: ${botId}.`;
|
||||
|
@ -166,7 +166,7 @@ export class GBMinService {
|
|||
// Build bot adapter.
|
||||
|
||||
const { min, adapter, conversationState } = await this.buildBotAdapter(
|
||||
instance,
|
||||
instance
|
||||
);
|
||||
|
||||
// Call the loadBot context.activity for all packages.
|
||||
|
@ -184,11 +184,11 @@ export class GBMinService {
|
|||
conversationState,
|
||||
min,
|
||||
instance,
|
||||
appPackages,
|
||||
appPackages
|
||||
);
|
||||
});
|
||||
logger.info(
|
||||
`GeneralBots(${instance.engineName}) listening on: ${url}.`,
|
||||
`GeneralBots(${instance.engineName}) listening on: ${url}.`
|
||||
);
|
||||
|
||||
// Serves individual URL for each bot user interface.
|
||||
|
@ -196,12 +196,12 @@ export class GBMinService {
|
|||
const uiUrl = `/${instance.botId}`;
|
||||
server.use(
|
||||
uiUrl,
|
||||
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, 'build')),
|
||||
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, 'build'))
|
||||
);
|
||||
|
||||
logger.info(`Bot UI ${uiPackage} accessible at: ${uiUrl}.`);
|
||||
const state = `${instance.instanceId}${Math.floor(
|
||||
Math.random() * 1000000000,
|
||||
Math.random() * 1000000000
|
||||
)}`;
|
||||
|
||||
// Clients get redirected here in order to create an OAuth authorize url and redirect them to AAD.
|
||||
|
@ -211,7 +211,7 @@ export class GBMinService {
|
|||
let authorizationUrl = UrlJoin(
|
||||
min.instance.authenticatorAuthorityHostUrl,
|
||||
min.instance.authenticatorTenant,
|
||||
'/oauth2/authorize',
|
||||
'/oauth2/authorize'
|
||||
);
|
||||
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
|
||||
min.instance.authenticatorClientId
|
||||
|
@ -229,7 +229,7 @@ export class GBMinService {
|
|||
server.get(`/${min.instance.botId}/token`, async (req, res) => {
|
||||
const state = await min.adminService.getValue(
|
||||
min.instance.instanceId,
|
||||
'AntiCSRFAttackState',
|
||||
'AntiCSRFAttackState'
|
||||
);
|
||||
|
||||
if (req.query.state !== state) {
|
||||
|
@ -242,8 +242,8 @@ export class GBMinService {
|
|||
const authenticationContext = new AuthenticationContext(
|
||||
UrlJoin(
|
||||
min.instance.authenticatorAuthorityHostUrl,
|
||||
min.instance.authenticatorTenant,
|
||||
),
|
||||
min.instance.authenticatorTenant
|
||||
)
|
||||
);
|
||||
|
||||
const resource = 'https://graph.microsoft.com';
|
||||
|
@ -263,27 +263,27 @@ export class GBMinService {
|
|||
await this.adminService.setValue(
|
||||
instance.instanceId,
|
||||
'refreshToken',
|
||||
token.refreshToken,
|
||||
token.refreshToken
|
||||
);
|
||||
await this.adminService.setValue(
|
||||
instance.instanceId,
|
||||
'accessToken',
|
||||
token.accessToken,
|
||||
token.accessToken
|
||||
);
|
||||
await this.adminService.setValue(
|
||||
instance.instanceId,
|
||||
'expiresOn',
|
||||
token.expiresOn.toString(),
|
||||
token.expiresOn.toString()
|
||||
);
|
||||
await this.adminService.setValue(
|
||||
instance.instanceId,
|
||||
'AntiCSRFAttackState',
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
res.redirect(min.instance.botEndpoint);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -301,7 +301,7 @@ export class GBMinService {
|
|||
// }
|
||||
// )
|
||||
// next()
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -316,8 +316,8 @@ export class GBMinService {
|
|||
url: 'https://directline.botframework.com/v3/directline/tokens/generate',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${instance.webchatKey}`,
|
||||
},
|
||||
Authorization: `Bearer ${instance.webchatKey}`
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -344,8 +344,8 @@ export class GBMinService {
|
|||
url: 'https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Ocp-Apim-Subscription-Key': instance.speechKey,
|
||||
},
|
||||
'Ocp-Apim-Subscription-Key': instance.speechKey
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -359,7 +359,7 @@ export class GBMinService {
|
|||
private async buildBotAdapter(instance: any) {
|
||||
const adapter = new BotFrameworkAdapter({
|
||||
appId: instance.marketplaceId,
|
||||
appPassword: instance.marketplacePassword,
|
||||
appPassword: instance.marketplacePassword
|
||||
});
|
||||
|
||||
const storage = new MemoryStorage();
|
||||
|
@ -395,7 +395,7 @@ export class GBMinService {
|
|||
GBKBPackage,
|
||||
GBAnalyticsPackage,
|
||||
GBCustomerSatisfactionPackage,
|
||||
GBWhatsappPackage,
|
||||
GBWhatsappPackage
|
||||
].forEach(sysPackage => {
|
||||
const p = Object.create(sysPackage.prototype) as IGBPackage;
|
||||
p.loadBot(min);
|
||||
|
@ -406,12 +406,12 @@ export class GBMinService {
|
|||
p.channel.received(req, res);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
appPackages.forEach(e => {
|
||||
e.sysPackages = sysPackages;
|
||||
e.loadBot(min);
|
||||
}, this);
|
||||
}, this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,7 +424,7 @@ export class GBMinService {
|
|||
conversationState: ConversationState,
|
||||
min: any,
|
||||
instance: any,
|
||||
appPackages: any[],
|
||||
appPackages: any[]
|
||||
) {
|
||||
return adapter.processActivity(req, res, async context => {
|
||||
const state = conversationState.get(context);
|
||||
|
@ -439,7 +439,7 @@ export class GBMinService {
|
|||
instanceId: instance.instanceId,
|
||||
botId: instance.botId,
|
||||
theme: instance.theme ? instance.theme : 'default.gbtheme',
|
||||
secret: instance.webchatKey,
|
||||
secret: instance.webchatKey
|
||||
});
|
||||
user.loaded = true;
|
||||
user.subjects = [];
|
||||
|
@ -449,7 +449,7 @@ export class GBMinService {
|
|||
logger.info(
|
||||
`User>: ${context.activity.text} (${context.activity.type}, ${
|
||||
context.activity.name
|
||||
}, ${context.activity.channelId}, {context.activity.value})`,
|
||||
}, ${context.activity.channelId}, {context.activity.value})`
|
||||
);
|
||||
if (
|
||||
context.activity.type === 'conversationUpdate' &&
|
||||
|
@ -478,7 +478,7 @@ export class GBMinService {
|
|||
// Checks for /menu JSON signature.
|
||||
} else if (context.activity.text.startsWith('{"title"')) {
|
||||
await step.beginDialog('/menu', {
|
||||
data: JSON.parse(context.activity.text),
|
||||
data: JSON.parse(context.activity.text)
|
||||
});
|
||||
|
||||
// Otherwise, continue to the active dialog in the stack.
|
||||
|
@ -487,7 +487,7 @@ export class GBMinService {
|
|||
await step.continueDialog();
|
||||
} else {
|
||||
await step.beginDialog('/answer', {
|
||||
query: context.activity.text,
|
||||
query: context.activity.text
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -504,18 +504,18 @@ export class GBMinService {
|
|||
await step.beginDialog('/menu');
|
||||
} else if (context.activity.name === 'giveFeedback') {
|
||||
await step.beginDialog('/feedback', {
|
||||
fromMenu: true,
|
||||
fromMenu: true
|
||||
});
|
||||
} else if (context.activity.name === 'showFAQ') {
|
||||
await step.beginDialog('/faq');
|
||||
} else if (context.activity.name === 'answerEvent') {
|
||||
await step.beginDialog('/answerEvent', {
|
||||
questionId: (context.activity as any).data,
|
||||
fromFaq: true,
|
||||
fromFaq: true
|
||||
});
|
||||
} else if (context.activity.name === 'quality') {
|
||||
await step.beginDialog('/quality', {
|
||||
score: (context.activity as any).data,
|
||||
score: (context.activity as any).data
|
||||
});
|
||||
} else if (context.activity.name === 'updateToken') {
|
||||
const token = (context.activity as any).data;
|
||||
|
@ -529,7 +529,7 @@ export class GBMinService {
|
|||
logger.error(msg);
|
||||
|
||||
await step.context.sendActivity(
|
||||
Messages[step.context.activity.locale].very_sorry_about_error,
|
||||
Messages[step.context.activity.locale].very_sorry_about_error
|
||||
);
|
||||
await step.beginDialog('/ask', { isReturning: true });
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ const UrlJoin = require('url-join');
|
|||
*/
|
||||
|
||||
export class GBVMService implements IGBCoreService {
|
||||
|
||||
private script = new vm.Script();
|
||||
|
||||
public async loadJS(
|
||||
|
@ -63,18 +62,15 @@ export class GBVMService implements IGBCoreService {
|
|||
deployer: GBDeployer,
|
||||
localPath: string
|
||||
): Promise<void> {
|
||||
|
||||
const code = fs.readFileSync(UrlJoin(localPath, filename), 'utf8');
|
||||
const sandbox = new DialogClass(min);
|
||||
|
||||
localPath = UrlJoin(localPath, 'chat.dialog.js');
|
||||
const code: string = fs.readFileSync(UrlJoin(localPath, filename), 'utf8');
|
||||
const sandbox: DialogClass = new DialogClass(min);
|
||||
const context = vm.createContext(sandbox);
|
||||
this.script.runInContext(context);
|
||||
|
||||
this.script.runInContext(code, context);
|
||||
console.log(util.inspect(sandbox));
|
||||
|
||||
await deployer.deployScriptToStorage(
|
||||
min.instanceId,
|
||||
filename
|
||||
);
|
||||
await deployer.deployScriptToStorage(min.instanceId, filename);
|
||||
logger.info(`[GBVMService] Finished loading of ${filename}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ function ICanSendEmails()
|
|||
|
||||
bot.say ("Please, what's your e-mail address?")
|
||||
email = bot.expectEmail()
|
||||
bot.sendMail (email, "Olá", "I'm sending a General Bots VBA e-mail.")
|
||||
bot.sendMail (email, "Hello", "I'm sending a General Bots VBA e-mail.")
|
||||
|
||||
end function
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -30,11 +30,15 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @fileoverview Knowledge base services and logic.
|
||||
*/
|
||||
|
||||
const logger = require('../../../src/logger');
|
||||
const Path = require('path');
|
||||
const Fs = require('fs');
|
||||
const promise = require('bluebird');
|
||||
const parse = promise.promisify(require('csv-parse'));
|
||||
|
||||
const parse = require('bluebird').promisify(require('csv-parse'));
|
||||
const UrlJoin = require('url-join');
|
||||
const marked = require('marked');
|
||||
const path = require('path');
|
||||
|
@ -69,6 +73,7 @@ export class KBService {
|
|||
subjects.forEach(subject => {
|
||||
out.push(subject.title);
|
||||
});
|
||||
|
||||
return out.join(', ');
|
||||
}
|
||||
|
||||
|
@ -77,6 +82,7 @@ export class KBService {
|
|||
subjects.forEach(subject => {
|
||||
out.push(subject.internalId);
|
||||
});
|
||||
|
||||
return out.join(' ');
|
||||
}
|
||||
|
||||
|
@ -125,8 +131,10 @@ export class KBService {
|
|||
answerId: question.answerId
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.resolve({ question: question, answer: answer });
|
||||
}
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
|
@ -163,9 +171,9 @@ export class KBService {
|
|||
query = `${query} ${text}`;
|
||||
}
|
||||
}
|
||||
// TODO: Filter by instance. what = `${what}&$filter=instanceId eq ${instanceId}`
|
||||
query = `${query}&$filter=instanceId eq ${instance.instanceId}`;
|
||||
try {
|
||||
if (instance.searchKey && GBConfigService.get('STORAGE_DIALECT') == 'mssql') {
|
||||
if (instance.searchKey && GBConfigService.get('STORAGE_DIALECT') === 'mssql') {
|
||||
const service = new AzureSearch(
|
||||
instance.searchKey,
|
||||
instance.searchHost,
|
||||
|
@ -203,6 +211,7 @@ export class KBService {
|
|||
parentId: number
|
||||
): Promise<GuaribasSubject[]> {
|
||||
const where = { parentSubjectId: parentId, instanceId: instanceId };
|
||||
|
||||
return GuaribasSubject.findAll({
|
||||
where: where
|
||||
});
|
||||
|
@ -210,7 +219,7 @@ export class KBService {
|
|||
|
||||
public async getFaqBySubjectArray(from: string, subjects: any): Promise<GuaribasQuestion[]> {
|
||||
const where = {
|
||||
from: from, subject1: null, subject2: null, subject3: null, subject4:null
|
||||
from: from, subject1: null, subject2: null, subject3: null, subject4: null
|
||||
};
|
||||
|
||||
if (subjects) {
|
||||
|
@ -230,6 +239,7 @@ export class KBService {
|
|||
where.subject4 = subjects[3].internalId;
|
||||
}
|
||||
}
|
||||
|
||||
return await GuaribasQuestion.findAll({
|
||||
where: where
|
||||
});
|
||||
|
@ -250,6 +260,7 @@ export class KBService {
|
|||
let lastAnswer: GuaribasAnswer;
|
||||
|
||||
const data = await parse(file, opts);
|
||||
|
||||
return asyncPromise.eachSeries(data, async line => {
|
||||
|
||||
// Extracts values from columns in the current line.
|
||||
|
@ -262,7 +273,7 @@ export class KBService {
|
|||
|
||||
// Skips the first line.
|
||||
|
||||
if (!(subjectsText === 'subjects' && from == 'from')) {
|
||||
if (!(subjectsText === 'subjects' && from === 'from')) {
|
||||
let format = '.txt';
|
||||
|
||||
// Extracts answer from external media if any.
|
||||
|
@ -281,8 +292,10 @@ export class KBService {
|
|||
// Processes subjects hierarchy splitting by dots.
|
||||
|
||||
const subjectArray = subjectsText.split('.');
|
||||
let subject1: string, subject2: string, subject3: string,
|
||||
subject4: string;
|
||||
let subject1: string;
|
||||
let subject2: string;
|
||||
let subject3: string;
|
||||
let subject4: string;
|
||||
let indexer = 0;
|
||||
|
||||
subjectArray.forEach(element => {
|
||||
|
|
52
src/app.ts
52
src/app.ts
|
@ -75,8 +75,8 @@ export class GBServer {
|
|||
server.use(
|
||||
bodyParser.urlencoded({
|
||||
// to support URL-encoded bodies
|
||||
extended: true,
|
||||
}),
|
||||
extended: true
|
||||
})
|
||||
);
|
||||
|
||||
let bootInstance: IGBInstance;
|
||||
|
@ -93,40 +93,33 @@ export class GBServer {
|
|||
// Ensures cloud / on-premises infrastructure is setup.
|
||||
|
||||
logger.info(`Establishing a development local proxy (ngrok)...`);
|
||||
const proxyAddress = await core.ensureProxy(port);
|
||||
const proxyAddress: string = await core.ensureProxy(port);
|
||||
|
||||
logger.info(`Deploying packages...`);
|
||||
const deployer = new GBDeployer(core, new GBImporter(core));
|
||||
const azureDeployer = new AzureDeployerService(deployer);
|
||||
const adminService = new GBAdminService(core);
|
||||
const conversationalService = new GBConversationalService(core);
|
||||
bootInstance = await core.createBootInstance(
|
||||
core,
|
||||
azureDeployer,
|
||||
proxyAddress,
|
||||
);
|
||||
const importer: GBImporter = new GBImporter(core);
|
||||
const deployer: GBDeployer = new GBDeployer(core, importer);
|
||||
const azureDeployer: AzureDeployerService = new AzureDeployerService(deployer);
|
||||
const adminService: GBAdminService = new GBAdminService(core);
|
||||
const conversationalService: GBConversationalService = new GBConversationalService(core);
|
||||
core.ensureAdminIsSecured();
|
||||
core.loadSysPackages(core);
|
||||
|
||||
const bootInstance = await core.createBootInstance(core, azureDeployer, proxyAddress);
|
||||
await core.checkStorage(azureDeployer);
|
||||
await core.loadSysPackages(core);
|
||||
await deployer.deployPackages(core, server, appPackages);
|
||||
|
||||
logger.info(`Publishing instances...`);
|
||||
let instances: GuaribasInstance[] = await core.loadAllInstances(
|
||||
core,
|
||||
azureDeployer,
|
||||
proxyAddress,
|
||||
);
|
||||
instances = await core.ensureInstances(
|
||||
instances,
|
||||
bootInstance,
|
||||
core
|
||||
);
|
||||
const packageInstance = await importer.importIfNotExistsBotPackage('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);
|
||||
|
||||
const minService = new GBMinService(
|
||||
core,
|
||||
conversationalService,
|
||||
adminService,
|
||||
deployer,
|
||||
);
|
||||
// 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);
|
||||
|
||||
logger.info(`The Bot Server is in RUNNING mode...`);
|
||||
|
@ -141,7 +134,6 @@ export class GBServer {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// First line to run.
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @fileoverview Logging support.
|
||||
*/
|
||||
|
||||
const { createLogger, format, transports } = require('winston');
|
||||
|
||||
const config = {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"no-var-requires":false,
|
||||
"typedef":false,
|
||||
"variable-name": false,
|
||||
"no-parameter-properties": false,
|
||||
"no-reserved-keywords": false,
|
||||
|
@ -34,6 +36,6 @@
|
|||
"export-name":false,
|
||||
"no-relative-imports": false,
|
||||
"no-backbone-get-set-outside-model": false,
|
||||
"max-line-length": [true,{"limit":80,"ignore-pattern":"^\\s+\\*"}]
|
||||
"max-line-length": [true,{"limit":120,"ignore-pattern":"^\\s+\\*"}]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue