fix(startup): Startup improved and more checks added.
This commit is contained in:
parent
8490f5ed06
commit
5d6c60ed6d
6 changed files with 452 additions and 426 deletions
|
@ -63,6 +63,10 @@ export class AdminDialog extends IGBDialog {
|
||||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||||
|
if (!additionalPath)
|
||||||
|
{
|
||||||
|
throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.');
|
||||||
|
}
|
||||||
await deployer.deployPackageFromLocalPath(min, UrlJoin(additionalPath, packageName));
|
await deployer.deployPackageFromLocalPath(min, UrlJoin(additionalPath, packageName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@ export class AzureDeployerService extends GBService {
|
||||||
instance.storageServer = storageServer;
|
instance.storageServer = storageServer;
|
||||||
|
|
||||||
logger.info(`Deploying Search...`);
|
logger.info(`Deploying Search...`);
|
||||||
const searchName = `${name}-search`;
|
const searchName = `${name}-search`.toLowerCase();
|
||||||
await this.createSearch(name, searchName, instance.cloudLocation);
|
await this.createSearch(name, searchName, instance.cloudLocation);
|
||||||
const searchKeys = await this.searchClient.adminKeys.get(
|
const searchKeys = await this.searchClient.adminKeys.get(
|
||||||
name,
|
name,
|
||||||
|
@ -473,7 +473,7 @@ export class AzureDeployerService extends GBService {
|
||||||
const retrieveBotId = () => {
|
const retrieveBotId = () => {
|
||||||
if (!botId) {
|
if (!botId) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`${GBAdminService.GB_PROMPT}Bot Id must only contain lowercase letters, digits or dashes, cannot start or end with or contain consecutive dashes and is limited from 4 to 42 characters long.\n`
|
`${GBAdminService.GB_PROMPT}Choose a unique bot Id containing lowercase letters, digits or dashes (cannot use dash as the first two or last one characters), cannot start or end with or contain consecutive dashes and having 4 to 42 characters long.\n`
|
||||||
);
|
);
|
||||||
process.stdout.write(`${GBAdminService.GB_PROMPT}BOT_ID:`);
|
process.stdout.write(`${GBAdminService.GB_PROMPT}BOT_ID:`);
|
||||||
botId = scanf('%s').replace(/(\n|\r)+$/, ''); // TODO: Update this regexp to match description of it.
|
botId = scanf('%s').replace(/(\n|\r)+$/, ''); // TODO: Update this regexp to match description of it.
|
||||||
|
|
|
@ -218,21 +218,22 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,13 +45,13 @@ const express = require('express');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
|
|
||||||
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
import { GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
||||||
import { GBError } from 'botlib';
|
import { GBError,IGBPackage } from 'botlib';
|
||||||
import { IGBPackage } from 'botlib';
|
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||||
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel';
|
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel';
|
||||||
import { KBService } from './../../kb.gbapp/services/KBService';
|
import { KBService } from './../../kb.gbapp/services/KBService';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService';
|
||||||
|
import { GBCoreService } from './GBCoreService';
|
||||||
import { GBImporter } from './GBImporterService';
|
import { GBImporter } from './GBImporterService';
|
||||||
import { GBVMService } from './GBVMService';
|
import { GBVMService } from './GBVMService';
|
||||||
|
|
||||||
|
@ -77,9 +77,10 @@ export class GBDeployer {
|
||||||
*
|
*
|
||||||
* Performs package deployment in all .gbai or default.
|
* Performs package deployment in all .gbai or default.
|
||||||
*
|
*
|
||||||
* */
|
*/
|
||||||
public deployPackages(core: IGBCoreService, server: any, appPackages: IGBPackage[]) {
|
public async deployPackages(core: IGBCoreService, server: any, appPackages: IGBPackage[]) {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
|
||||||
return new Promise(
|
return new Promise(
|
||||||
(resolve: any, reject: any): any => {
|
(resolve: any, reject: any): any => {
|
||||||
let totalPackages = 0;
|
let totalPackages = 0;
|
||||||
|
@ -121,106 +122,30 @@ export class GBDeployer {
|
||||||
doIt(e);
|
doIt(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Deploys all .gbapp files first. */
|
// Deploys all .gbapp files first.
|
||||||
|
|
||||||
let appPackagesProcessed = 0;
|
const appPackagesProcessed = this.deployAppPackages(gbappPackages, core, appPackages);
|
||||||
|
|
||||||
gbappPackages.forEach(e => {
|
|
||||||
// Skips .gbapp inside deploy folder.
|
|
||||||
if (!e.startsWith('packages')) {
|
|
||||||
logger.info(`Deploying app: ${e}...`);
|
|
||||||
import(e)
|
|
||||||
.then(m => {
|
|
||||||
const p = new m.Package();
|
|
||||||
p.loadPackage(core, core.sequelize);
|
|
||||||
appPackages.push(p);
|
|
||||||
logger.info(`App (.gbapp) deployed: ${e}.`);
|
|
||||||
appPackagesProcessed++;
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
logger.error(`Error deploying App (.gbapp): ${e}: ${err}`);
|
|
||||||
appPackagesProcessed++;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
appPackagesProcessed++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
WaitUntil()
|
WaitUntil()
|
||||||
.interval(1000)
|
.interval(1000)
|
||||||
.times(10)
|
.times(10)
|
||||||
.condition(function(cb) {
|
.condition(cb => {
|
||||||
logger.info(`Waiting for app package deployment...`);
|
logger.info(`Waiting for app package deployment...`);
|
||||||
cb(appPackagesProcessed == gbappPackages.length);
|
cb(appPackagesProcessed === gbappPackages.length);
|
||||||
})
|
})
|
||||||
.done(async result => {
|
.done(async result => {
|
||||||
logger.info(`App Package deployment done.`);
|
logger.info(`App Package deployment done.`);
|
||||||
|
|
||||||
try {
|
({ generalPackages, totalPackages } = await this.deployDataPackages(
|
||||||
await core.syncDatabaseStructure();
|
core,
|
||||||
} catch (e) {
|
botPackages,
|
||||||
throw e;
|
_this,
|
||||||
}
|
generalPackages,
|
||||||
|
server,
|
||||||
/** Deploys all .gbot files first. */
|
reject,
|
||||||
|
totalPackages,
|
||||||
botPackages.forEach(e => {
|
resolve
|
||||||
if (e !== 'packages\\boot.gbot') {
|
));
|
||||||
logger.info(`Deploying bot: ${e}...`);
|
|
||||||
_this.deployBot(e);
|
|
||||||
logger.info(`Bot: ${e} deployed...`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Then all remaining generalPackages are loaded. */
|
|
||||||
|
|
||||||
generalPackages = generalPackages.filter(p => !p.endsWith('.git'));
|
|
||||||
|
|
||||||
generalPackages.forEach(filename => {
|
|
||||||
const filenameOnly = Path.basename(filename);
|
|
||||||
logger.info(`Deploying package: ${filename}...`);
|
|
||||||
|
|
||||||
/** Handles apps for general bots - .gbapp must stay out of deploy folder. */
|
|
||||||
|
|
||||||
if (Path.extname(filename) === '.gbapp' || Path.extname(filename) === '.gblib') {
|
|
||||||
/** Themes for bots. */
|
|
||||||
} else if (Path.extname(filename) === '.gbtheme') {
|
|
||||||
server.use('/themes/' + filenameOnly, express.static(filename));
|
|
||||||
logger.info(`Theme (.gbtheme) assets accessible at: ${'/themes/' + filenameOnly}.`);
|
|
||||||
|
|
||||||
/** Knowledge base for bots. */
|
|
||||||
} else if (Path.extname(filename) === '.gbkb') {
|
|
||||||
server.use('/kb/' + filenameOnly + '/subjects', express.static(UrlJoin(filename, 'subjects')));
|
|
||||||
logger.info(`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}.`);
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
totalPackages++;
|
|
||||||
});
|
|
||||||
|
|
||||||
WaitUntil()
|
|
||||||
.interval(100)
|
|
||||||
.times(5)
|
|
||||||
.condition(function(cb) {
|
|
||||||
logger.info(`Waiting for package deployment...`);
|
|
||||||
cb(totalPackages == generalPackages.length);
|
|
||||||
})
|
|
||||||
.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.'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
logger.info(`Package deployment done.`);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -363,9 +288,109 @@ export class GBDeployer {
|
||||||
public installDefaultGBUI() {
|
public installDefaultGBUI() {
|
||||||
const root = 'packages/default.gbui';
|
const root = 'packages/default.gbui';
|
||||||
if (!Fs.existsSync(`${root}/build`)) {
|
if (!Fs.existsSync(`${root}/build`)) {
|
||||||
|
logger.info(`Preparing default.gbui (it may take some additional time for the first time)...`);
|
||||||
Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
||||||
child_process.execSync('npm install', { cwd: root });
|
child_process.execSync('npm install', { cwd: root });
|
||||||
child_process.execSync('npm run build', { cwd: root });
|
child_process.execSync('npm run build', { cwd: root });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async deployDataPackages(
|
||||||
|
core: GBCoreService,
|
||||||
|
botPackages: string[],
|
||||||
|
_this: this,
|
||||||
|
generalPackages: string[],
|
||||||
|
server: any,
|
||||||
|
reject: any,
|
||||||
|
totalPackages: number,
|
||||||
|
resolve: any
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
await core.syncDatabaseStructure();
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
generalPackages = generalPackages.filter(p => !p.endsWith('.git'));
|
||||||
|
generalPackages.forEach(filename => {
|
||||||
|
const filenameOnly = Path.basename(filename);
|
||||||
|
logger.info(`Deploying package: ${filename}...`);
|
||||||
|
|
||||||
|
// Handles apps for general bots - .gbapp must stay out of deploy folder.
|
||||||
|
|
||||||
|
if (Path.extname(filename) === '.gbapp' || Path.extname(filename) === '.gblib') {
|
||||||
|
// Themes for bots.
|
||||||
|
} else if (Path.extname(filename) === '.gbtheme') {
|
||||||
|
server.use('/themes/' + filenameOnly, express.static(filename));
|
||||||
|
logger.info(`Theme (.gbtheme) assets accessible at: ${'/themes/' + filenameOnly}.`);
|
||||||
|
} else if (Path.extname(filename) === '.gbkb') {
|
||||||
|
server.use('/kb/' + filenameOnly + '/subjects', express.static(UrlJoin(filename, 'subjects')));
|
||||||
|
logger.info(`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}.`);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
totalPackages++;
|
||||||
|
});
|
||||||
|
|
||||||
|
WaitUntil()
|
||||||
|
.interval(100)
|
||||||
|
.times(5)
|
||||||
|
.condition(cb => {
|
||||||
|
logger.info(`Waiting for package deployment...`);
|
||||||
|
cb(totalPackages === generalPackages.length);
|
||||||
|
})
|
||||||
|
.done(result => {
|
||||||
|
if (botPackages.length === 0) {
|
||||||
|
logger.info('Use ADDITIONAL_DEPLOY_PATH to point to a .gbai package folder (no external packages).');
|
||||||
|
} else {
|
||||||
|
logger.info(`Package deployment done.`);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
return { generalPackages, totalPackages };
|
||||||
|
}
|
||||||
|
|
||||||
|
private deployAppPackages(gbappPackages: string[], core: any, appPackages: any[]) {
|
||||||
|
let appPackagesProcessed = 0;
|
||||||
|
gbappPackages.forEach(e => {
|
||||||
|
// Skips .gbapp inside deploy folder.
|
||||||
|
if (!e.startsWith('packages')) {
|
||||||
|
logger.info(`Deploying app: ${e}...`);
|
||||||
|
import(e)
|
||||||
|
.then(m => {
|
||||||
|
const p = new m.Package();
|
||||||
|
p.loadPackage(core, core.sequelize);
|
||||||
|
appPackages.push(p);
|
||||||
|
logger.info(`App (.gbapp) deployed: ${e}.`);
|
||||||
|
appPackagesProcessed++;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.error(`Error deploying App (.gbapp): ${e}: ${err}`);
|
||||||
|
appPackagesProcessed++;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
appPackagesProcessed++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return appPackagesProcessed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,333 +30,322 @@
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
import GBMarkdownPlayer from "./players/GBMarkdownPlayer.js";
|
import GBMarkdownPlayer from './players/GBMarkdownPlayer.js';
|
||||||
import GBImagePlayer from "./players/GBImagePlayer.js";
|
import GBImagePlayer from './players/GBImagePlayer.js';
|
||||||
import GBVideoPlayer from "./players/GBVideoPlayer.js";
|
import GBVideoPlayer from './players/GBVideoPlayer.js';
|
||||||
import GBLoginPlayer from "./players/GBLoginPlayer.js";
|
import GBLoginPlayer from './players/GBLoginPlayer.js';
|
||||||
import GBBulletPlayer from "./players/GBBulletPlayer.js";
|
import GBBulletPlayer from './players/GBBulletPlayer.js';
|
||||||
import SidebarMenu from "./components/SidebarMenu.js";
|
import SidebarMenu from './components/SidebarMenu.js';
|
||||||
import GBCss from "./components/GBCss.js";
|
import GBCss from './components/GBCss.js';
|
||||||
import { DirectLine } from "botframework-directlinejs";
|
import { DirectLine } from 'botframework-directlinejs';
|
||||||
import { ConnectionStatus } from "botframework-directlinejs";
|
import { ConnectionStatus } from 'botframework-directlinejs';
|
||||||
import { Chat } from "botframework-webchat";
|
import ReactWebChat from 'botframework-webchat';
|
||||||
import GBPowerBIPlayer from "./players/GBPowerBIPlayer.js";
|
import GBPowerBIPlayer from './players/GBPowerBIPlayer.js';
|
||||||
import { UserAgentApplication } from "msal";
|
import { UserAgentApplication } from 'msal';
|
||||||
|
|
||||||
class GBUIApp extends React.Component {
|
class GBUIApp extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
line: null,
|
line: null,
|
||||||
instance: null,
|
instance: null,
|
||||||
token: null,
|
token: null,
|
||||||
instanceClient: null
|
instanceClient: null
|
||||||
};
|
};
|
||||||
window.user = this.getUser()
|
window.user = this.getUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
sendToken(token) {
|
sendToken(token) {
|
||||||
|
setTimeout(() => {
|
||||||
setTimeout(() => {
|
window.line
|
||||||
window.line
|
.postActivity({
|
||||||
.postActivity({
|
type: 'event',
|
||||||
type: "event",
|
name: 'updateToken',
|
||||||
name: "updateToken",
|
data: token,
|
||||||
data: token,
|
locale: 'en-us',
|
||||||
locale: "en-us",
|
textFormat: 'plain',
|
||||||
textFormat: "plain",
|
timestamp: new Date().toISOString(),
|
||||||
timestamp: new Date().toISOString(),
|
from: this.getUser()
|
||||||
from: this.getUser()
|
})
|
||||||
})
|
.subscribe(() => {
|
||||||
.subscribe(() => {
|
window.userAgentApplication.logout();
|
||||||
window.userAgentApplication.logout();
|
console.log('updateToken done');
|
||||||
console.log("updateToken done")
|
|
||||||
});
|
|
||||||
}, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
send(command) {
|
|
||||||
window.line
|
|
||||||
.postActivity({
|
|
||||||
type: "event",
|
|
||||||
name: command,
|
|
||||||
locale: "en-us",
|
|
||||||
textFormat: "plain",
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
from: this.getUser()
|
|
||||||
})
|
|
||||||
.subscribe(console.log("EVENT SENT TO Guaribas."));
|
|
||||||
}
|
|
||||||
|
|
||||||
getUser() {
|
|
||||||
return { id: "webUser@gb", name: "You" };
|
|
||||||
}
|
|
||||||
|
|
||||||
postEvent(name, value) {
|
|
||||||
window.line.postActivity({
|
|
||||||
type: "event",
|
|
||||||
value: value,
|
|
||||||
from: this.getUser(),
|
|
||||||
name: name
|
|
||||||
});
|
});
|
||||||
|
}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(command) {
|
||||||
|
window.line
|
||||||
|
.postActivity({
|
||||||
|
type: 'event',
|
||||||
|
name: command,
|
||||||
|
locale: 'en-us',
|
||||||
|
textFormat: 'plain',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
from: this.getUser()
|
||||||
|
})
|
||||||
|
.subscribe(console.log('EVENT SENT TO Guaribas.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
getUser() {
|
||||||
|
return { id: 'webUser@gb', name: 'You' };
|
||||||
|
}
|
||||||
|
|
||||||
|
postEvent(name, value) {
|
||||||
|
window.line.postActivity({
|
||||||
|
type: 'event',
|
||||||
|
value: value,
|
||||||
|
from: this.getUser(),
|
||||||
|
name: name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
postMessage(value) {
|
||||||
|
window.line.postActivity({
|
||||||
|
type: 'message',
|
||||||
|
text: value,
|
||||||
|
from: this.getUser()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
configureChat() {
|
||||||
|
var botId = window.location.href.split('/')[3];
|
||||||
|
if (botId.indexOf('#') !== -1) {
|
||||||
|
botId = botId.split('#')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
postMessage(value) {
|
if (!botId || botId === '') {
|
||||||
window.line.postActivity({
|
botId = '[default]';
|
||||||
type: "message",
|
|
||||||
text: value,
|
|
||||||
from: this.getUser()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configureChat() {
|
fetch('/instances/' + botId)
|
||||||
var botId = window.location.href.split("/")[3];
|
.then(res => res.json())
|
||||||
if (botId.indexOf('#') !== -1) {
|
.then(
|
||||||
botId = botId.split("#")[0];
|
result => {
|
||||||
|
this.setState({ instanceClient: result });
|
||||||
|
this.setupBotConnection();
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.setState({
|
||||||
|
isLoaded: false,
|
||||||
|
err: error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!botId || botId === "") {
|
authenticate() {
|
||||||
botId = "[default]";
|
let _this_ = this;
|
||||||
|
let authority = 'https://login.microsoftonline.com/' + this.state.instanceClient.authenticatorTenant;
|
||||||
|
|
||||||
|
let graphScopes = ['Directory.AccessAsUser.All'];
|
||||||
|
|
||||||
|
let userAgentApplication = new UserAgentApplication(
|
||||||
|
this.state.instanceClient.authenticatorClientId,
|
||||||
|
authority,
|
||||||
|
function(errorDesc, token, error, tokenType) {
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
window.userAgentApplication = userAgentApplication;
|
||||||
|
|
||||||
fetch("/instances/" + botId)
|
if (!userAgentApplication.isCallback(window.location.hash) && window.parent === window && !window.opener) {
|
||||||
.then(res => res.json())
|
var user = userAgentApplication.getUser();
|
||||||
.then(
|
if (user) {
|
||||||
result => {
|
userAgentApplication.acquireTokenSilent(graphScopes).then(
|
||||||
this.setState({ instanceClient: result });
|
function(accessToken) {
|
||||||
this.setupBotConnection();
|
_this_.sendToken(accessToken);
|
||||||
},
|
},
|
||||||
error => {
|
function(error) {
|
||||||
this.setState({
|
console.log(error);
|
||||||
isLoaded: false,
|
}
|
||||||
err: error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
authenticate() {
|
|
||||||
let _this_ = this;
|
|
||||||
let authority =
|
|
||||||
"https://login.microsoftonline.com/" +
|
|
||||||
this.state.instanceClient.authenticatorTenant;
|
|
||||||
|
|
||||||
let graphScopes = ["Directory.AccessAsUser.All"];
|
|
||||||
|
|
||||||
let userAgentApplication = new UserAgentApplication(
|
|
||||||
this.state.instanceClient.authenticatorClientId,
|
|
||||||
authority,
|
|
||||||
function(errorDesc, token, error, tokenType) {
|
|
||||||
if (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
window.userAgentApplication = userAgentApplication;
|
}
|
||||||
|
|
||||||
if (!userAgentApplication.isCallback(window.location.hash) && window.parent === window && !window.opener) {
|
|
||||||
var user = userAgentApplication.getUser();
|
|
||||||
if (user) {
|
|
||||||
userAgentApplication.acquireTokenSilent(graphScopes).then(function(accessToken) {
|
|
||||||
_this_.sendToken(accessToken);
|
|
||||||
}, function(error) {
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setupBotConnection() {
|
setupBotConnection() {
|
||||||
let _this_ = this;
|
let _this_ = this;
|
||||||
window["botchatDebug"] = true;
|
window['botchatDebug'] = true;
|
||||||
|
|
||||||
const line = new DirectLine({
|
const line = new DirectLine({
|
||||||
secret: this.state.instanceClient.secret
|
secret: this.state.instanceClient.secret
|
||||||
|
});
|
||||||
|
|
||||||
|
line.connectionStatus$.subscribe(connectionStatus => {
|
||||||
|
if (connectionStatus === ConnectionStatus.Online) {
|
||||||
|
_this_.setState({ line: line });
|
||||||
|
window['botConnection'] = line;
|
||||||
|
line.postActivity({
|
||||||
|
type: 'event',
|
||||||
|
value: 'startGB',
|
||||||
|
from: this.getUser(),
|
||||||
|
name: 'startGB'
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
line.connectionStatus$.subscribe(connectionStatus => {
|
window.line = line;
|
||||||
if (connectionStatus === ConnectionStatus.Online) {
|
this.postEvent('startGB', true);
|
||||||
_this_.setState({ line: line });
|
|
||||||
line.postActivity({
|
|
||||||
type: "event",
|
|
||||||
value: "startGB",
|
|
||||||
from: this.getUser(),
|
|
||||||
name: "startGB"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
window.line = line;
|
line.activity$
|
||||||
this.postEvent("startGB", true);
|
.filter(activity => activity.type === 'event' && activity.name === 'loadInstance')
|
||||||
|
.subscribe(activity => {
|
||||||
|
_this_.setState({ instance: activity.value });
|
||||||
|
_this_.authenticate();
|
||||||
|
});
|
||||||
|
|
||||||
line.activity$
|
line.activity$
|
||||||
.filter(
|
.filter(activity => activity.type === 'event' && activity.name === 'stop')
|
||||||
activity =>
|
.subscribe(activity => {
|
||||||
activity.type === "event" && activity.name === "loadInstance"
|
if (_this_.player) {
|
||||||
)
|
_this_.player.stop();
|
||||||
.subscribe(activity => {
|
}
|
||||||
_this_.setState({ instance: activity.value });
|
});
|
||||||
_this_.authenticate()
|
|
||||||
});
|
|
||||||
|
|
||||||
line.activity$
|
line.activity$
|
||||||
.filter(activity => activity.type === "event" && activity.name === "stop")
|
.filter(activity => activity.type === 'event' && activity.name === 'play')
|
||||||
.subscribe(activity => {
|
.subscribe(activity => {
|
||||||
if (_this_.player) {
|
_this_.setState({ playerType: activity.value.playerType });
|
||||||
_this_.player.stop();
|
_this_.player.play(activity.value.data);
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
line.activity$
|
componentDidMount() {
|
||||||
.filter(activity => activity.type === "event" && activity.name === "play")
|
this.configureChat();
|
||||||
.subscribe(activity => {
|
}
|
||||||
_this_.setState({ playerType: activity.value.playerType });
|
|
||||||
_this_.player.play(activity.value.data);
|
render() {
|
||||||
});
|
let playerComponent = '';
|
||||||
|
|
||||||
|
if (this.state.playerType) {
|
||||||
|
switch (this.state.playerType) {
|
||||||
|
case 'markdown':
|
||||||
|
playerComponent = (
|
||||||
|
<GBMarkdownPlayer
|
||||||
|
app={this}
|
||||||
|
ref={player => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'bullet':
|
||||||
|
playerComponent = (
|
||||||
|
<GBBulletPlayer
|
||||||
|
app={this}
|
||||||
|
ref={player => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'video':
|
||||||
|
playerComponent = (
|
||||||
|
<GBVideoPlayer
|
||||||
|
app={this}
|
||||||
|
ref={player => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'image':
|
||||||
|
playerComponent = (
|
||||||
|
<GBImagePlayer
|
||||||
|
app={this}
|
||||||
|
ref={player => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'pbi':
|
||||||
|
playerComponent = (
|
||||||
|
<GBPowerBIPlayer
|
||||||
|
app={this}
|
||||||
|
ref={player => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'login':
|
||||||
|
playerComponent = (
|
||||||
|
<GBLoginPlayer
|
||||||
|
app={this}
|
||||||
|
ref={player => {
|
||||||
|
this.player = player;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('GBERROR: Unknow player type specified on message from server.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
let chat = <div />;
|
||||||
this.configureChat();
|
let gbCss = <div />;
|
||||||
|
|
||||||
|
let sideBar = (
|
||||||
|
<div className="sidebar">
|
||||||
|
<SidebarMenu chat={this.chat} instance={this.state.instance} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.state.line && this.state.instance) {
|
||||||
|
gbCss = <GBCss instance={this.state.instance} />;
|
||||||
|
|
||||||
|
// let speechOptions;
|
||||||
|
// let token = this.state.instanceClient.speechToken;
|
||||||
|
|
||||||
|
// speechOptions = {
|
||||||
|
// speechRecognizer: new SpeechRecognizer({
|
||||||
|
// locale: "pt-br",
|
||||||
|
// fetchCallback: (authFetchEventId) => getToken(),
|
||||||
|
// fetchOnExpiryCallback: (authFetchEventId) => getToken()
|
||||||
|
// }),
|
||||||
|
// speechSynthesizer: new SpeechSynthesizer({
|
||||||
|
// fetchCallback: (authFetchEventId) => getToken(),
|
||||||
|
// fetchOnExpiryCallback: (authFetchEventId) => getToken(),
|
||||||
|
// gender: SynthesisGender.Male,
|
||||||
|
// voiceName: 'Microsoft Server Speech Text to Speech Voice (pt-BR, Daniel, Apollo)'
|
||||||
|
// })
|
||||||
|
// };
|
||||||
|
|
||||||
|
chat = (
|
||||||
|
<ReactWebChat
|
||||||
|
ref={chat => {
|
||||||
|
this.chat = chat;
|
||||||
|
}}
|
||||||
|
locale={'pt-br'}
|
||||||
|
botConnection={this.state.line}
|
||||||
|
user={this.getUser()}
|
||||||
|
bot={{ id: 'bot@gb', name: 'Bot' }}
|
||||||
|
// speechOptions={speechOptions}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
if (!this.state.instance) {
|
||||||
|
sideBar = '';
|
||||||
|
|
||||||
let playerComponent = "";
|
|
||||||
|
|
||||||
if (this.state.playerType) {
|
|
||||||
switch (this.state.playerType) {
|
|
||||||
case "markdown":
|
|
||||||
playerComponent = (
|
|
||||||
<GBMarkdownPlayer
|
|
||||||
app={this}
|
|
||||||
ref={player => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "bullet":
|
|
||||||
playerComponent = (
|
|
||||||
<GBBulletPlayer
|
|
||||||
app={this}
|
|
||||||
ref={player => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "video":
|
|
||||||
playerComponent = (
|
|
||||||
<GBVideoPlayer
|
|
||||||
app={this}
|
|
||||||
ref={player => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "image":
|
|
||||||
playerComponent = (
|
|
||||||
<GBImagePlayer
|
|
||||||
app={this}
|
|
||||||
ref={player => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "pbi":
|
|
||||||
playerComponent = (
|
|
||||||
<GBPowerBIPlayer
|
|
||||||
app={this}
|
|
||||||
ref={player => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "login":
|
|
||||||
playerComponent = (
|
|
||||||
<GBLoginPlayer
|
|
||||||
app={this}
|
|
||||||
ref={player => {
|
|
||||||
this.player = player;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log(
|
|
||||||
"GBERROR: Unknow player type specified on message from server."
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let chat = <div />;
|
|
||||||
let gbCss = <div />;
|
|
||||||
|
|
||||||
|
|
||||||
let sideBar = (
|
|
||||||
<div className="sidebar">
|
|
||||||
<SidebarMenu chat={this.chat} instance={this.state.instance} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.state.line && this.state.instance) {
|
|
||||||
gbCss = <GBCss instance={this.state.instance} />;
|
|
||||||
|
|
||||||
// let speechOptions;
|
|
||||||
// let token = this.state.instanceClient.speechToken;
|
|
||||||
|
|
||||||
// speechOptions = {
|
|
||||||
// speechRecognizer: new SpeechRecognizer({
|
|
||||||
// locale: "pt-br",
|
|
||||||
// fetchCallback: (authFetchEventId) => getToken(),
|
|
||||||
// fetchOnExpiryCallback: (authFetchEventId) => getToken()
|
|
||||||
// }),
|
|
||||||
// speechSynthesizer: new SpeechSynthesizer({
|
|
||||||
// fetchCallback: (authFetchEventId) => getToken(),
|
|
||||||
// fetchOnExpiryCallback: (authFetchEventId) => getToken(),
|
|
||||||
// gender: SynthesisGender.Male,
|
|
||||||
// voiceName: 'Microsoft Server Speech Text to Speech Voice (pt-BR, Daniel, Apollo)'
|
|
||||||
// })
|
|
||||||
// };
|
|
||||||
|
|
||||||
chat = (
|
|
||||||
<Chat
|
|
||||||
ref={chat => {
|
|
||||||
this.chat = chat;
|
|
||||||
}}
|
|
||||||
locale={'pt-br'}
|
|
||||||
botConnection={this.state.line}
|
|
||||||
user={this.getUser()}
|
|
||||||
bot={{ id: "bot@gb", name: "Bot" }}
|
|
||||||
// speechOptions={speechOptions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.state.instance) {
|
|
||||||
sideBar = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{gbCss}
|
|
||||||
{sideBar}
|
|
||||||
<div className="player">{playerComponent}</div>
|
|
||||||
{chat}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{gbCss}
|
||||||
|
{sideBar}
|
||||||
|
<div className="player">{playerComponent}</div>
|
||||||
|
{chat}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GBUIApp;
|
export default GBUIApp;
|
||||||
|
|
39
src/app.ts
39
src/app.ts
|
@ -90,20 +90,20 @@ export class GBServer {
|
||||||
|
|
||||||
GBConfigService.init();
|
GBConfigService.init();
|
||||||
const core = new GBCoreService();
|
const core = new GBCoreService();
|
||||||
|
core.ensureAdminIsSecured();
|
||||||
|
|
||||||
// Ensures cloud / on-premises infrastructure is setup.
|
|
||||||
|
|
||||||
logger.info(`Establishing a development local proxy (ngrok)...`);
|
|
||||||
|
|
||||||
const proxyAddress: string = await core.ensureProxy(port);
|
|
||||||
|
|
||||||
logger.info(`Deploying packages...`);
|
|
||||||
const importer: GBImporter = new GBImporter(core);
|
const importer: GBImporter = new GBImporter(core);
|
||||||
const deployer: GBDeployer = new GBDeployer(core, importer);
|
const deployer: GBDeployer = new GBDeployer(core, importer);
|
||||||
const azureDeployer: AzureDeployerService = new AzureDeployerService(deployer);
|
const azureDeployer: AzureDeployerService = new AzureDeployerService(deployer);
|
||||||
const adminService: GBAdminService = new GBAdminService(core);
|
const adminService: GBAdminService = new GBAdminService(core);
|
||||||
const conversationalService: GBConversationalService = new GBConversationalService(core);
|
const conversationalService: GBConversationalService = new GBConversationalService(core);
|
||||||
core.ensureAdminIsSecured();
|
|
||||||
|
// Ensure that local development proxy is setup.
|
||||||
|
|
||||||
|
logger.info(`Establishing a development local proxy (ngrok)...`);
|
||||||
|
const proxyAddress: string = await core.ensureProxy(port);
|
||||||
|
|
||||||
|
// Creates a boot instance or load it frmo storage.
|
||||||
|
|
||||||
let bootInstance: IGBInstance = null;
|
let bootInstance: IGBInstance = null;
|
||||||
try {
|
try {
|
||||||
|
@ -113,10 +113,16 @@ export class GBServer {
|
||||||
await core.initStorage();
|
await core.initStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deploys system and user packages.
|
||||||
|
|
||||||
|
logger.info(`Deploying packages...`);
|
||||||
await core.loadSysPackages(core);
|
await core.loadSysPackages(core);
|
||||||
await core.checkStorage(azureDeployer);
|
await core.checkStorage(azureDeployer);
|
||||||
await deployer.deployPackages(core, server, appPackages);
|
await deployer.deployPackages(core, server, appPackages);
|
||||||
|
|
||||||
|
|
||||||
|
// Loads all bot instances.
|
||||||
|
|
||||||
logger.info(`Publishing instances...`);
|
logger.info(`Publishing instances...`);
|
||||||
const packageInstance = await importer.importIfNotExistsBotPackage(
|
const packageInstance = await importer.importIfNotExistsBotPackage(
|
||||||
GBConfigService.get('CLOUD_GROUP'),
|
GBConfigService.get('CLOUD_GROUP'),
|
||||||
|
@ -127,20 +133,27 @@ export class GBServer {
|
||||||
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);
|
||||||
if(!bootInstance) {
|
if (!bootInstance) {
|
||||||
bootInstance = instances[0];
|
bootInstance = instances[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Builds minimal service infrastructure.
|
||||||
|
|
||||||
const minService: GBMinService = new GBMinService(core, conversationalService, adminService, deployer);
|
const minService: GBMinService = new GBMinService(core, conversationalService, adminService, deployer);
|
||||||
await minService.buildMin(bootInstance, server, appPackages, instances, deployer);
|
await minService.buildMin(bootInstance, server, appPackages, instances, deployer);
|
||||||
|
|
||||||
logger.info(`Preparing default.gbui (it may take some additional time for the first time)...`);
|
// Deployment of local applications for the first time.
|
||||||
|
|
||||||
deployer.installDefaultGBUI();
|
deployer.installDefaultGBUI();
|
||||||
|
|
||||||
logger.info(`The Bot Server is in RUNNING mode...`);
|
logger.info(`The Bot Server is in RUNNING mode...`);
|
||||||
|
|
||||||
|
// Opens Navigator.
|
||||||
|
|
||||||
core.openBrowserInDevelopment();
|
core.openBrowserInDevelopment();
|
||||||
|
|
||||||
return core;
|
return core;
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`STOP: ${err} ${err.stack ? err.stack : ''}`);
|
logger.error(`STOP: ${err} ${err.stack ? err.stack : ''}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -152,10 +165,4 @@ export class GBServer {
|
||||||
|
|
||||||
// First line to run.
|
// First line to run.
|
||||||
|
|
||||||
// const path = 'packages/default.gbdialog';
|
|
||||||
// const file = 'bot.vbs';
|
|
||||||
// const source =(path + '/' + file);
|
|
||||||
// let s = new GBVMService();
|
|
||||||
// s.run(source, path, null, null, null)
|
|
||||||
|
|
||||||
GBServer.run();
|
GBServer.run();
|
||||||
|
|
Loading…
Add table
Reference in a new issue