feat(whatsapp.gblib): Same chat-api provider now shared between instances and deploy improvements.
This commit is contained in:
parent
9a961e72a1
commit
b2da413f0f
9 changed files with 54 additions and 47 deletions
|
@ -73,7 +73,6 @@
|
||||||
"cli-spinner": "0.2.10",
|
"cli-spinner": "0.2.10",
|
||||||
"csv-parse": "4.4.1",
|
"csv-parse": "4.4.1",
|
||||||
"dotenv-extended": "2.4.0",
|
"dotenv-extended": "2.4.0",
|
||||||
"empty-dir": "^2.0.0",
|
|
||||||
"express": "4.16.4",
|
"express": "4.16.4",
|
||||||
"express-promise-router": "3.0.3",
|
"express-promise-router": "3.0.3",
|
||||||
"express-remove-route": "^1.0.0",
|
"express-remove-route": "^1.0.0",
|
||||||
|
|
|
@ -537,6 +537,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
const resChannel = await httpClient.sendRequest(req);
|
const resChannel = await httpClient.sendRequest(req);
|
||||||
const key = JSON.parse(resChannel.bodyAsText).properties.properties.sites[0].key;
|
const key = JSON.parse(resChannel.bodyAsText).properties.properties.sites[0].key;
|
||||||
instance.webchatKey = key;
|
instance.webchatKey = key;
|
||||||
|
instance.whatsappBotKey = key;
|
||||||
resolve(instance);
|
resolve(instance);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
|
|
|
@ -43,7 +43,7 @@ const WaitUntil = require('wait-until');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
const graph = require('@microsoft/microsoft-graph-client');
|
const graph = require('@microsoft/microsoft-graph-client');
|
||||||
const emptyDir = require('empty-dir');
|
const rimraf = require('rimraf');
|
||||||
|
|
||||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
|
@ -190,6 +190,8 @@ export class GBDeployer {
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
console.log(GBServer.globals.bootInstance);
|
||||||
instance = Object.assign(instance, GBServer.globals.bootInstance);
|
instance = Object.assign(instance, GBServer.globals.bootInstance);
|
||||||
instance = await service.internalDeployBot(
|
instance = await service.internalDeployBot(
|
||||||
instance,
|
instance,
|
||||||
|
@ -214,17 +216,13 @@ export class GBDeployer {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deploys a bot to the storage.
|
* UndDeploys a bot to the storage.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
|
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
|
||||||
const group = GBConfigService.get('CLOUD_GROUP');
|
const group = GBConfigService.get('CLOUD_GROUP');
|
||||||
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
|
||||||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
|
||||||
|
|
||||||
if (await service.botExists(botId, group)) {
|
if (await service.botExists(botId, group)) {
|
||||||
|
|
||||||
|
@ -235,10 +233,14 @@ export class GBDeployer {
|
||||||
}
|
}
|
||||||
GBServer.globals.minService.unmountBot(botId);
|
GBServer.globals.minService.unmountBot(botId);
|
||||||
await this.core.deleteInstance(botId);
|
await this.core.deleteInstance(botId);
|
||||||
const packageFolder = urlJoin(process.env.PWD, 'work', packageName);
|
const packageFolder =Path.join(process.env.PWD, 'work', packageName);
|
||||||
await emptyDir(packageFolder);
|
rimraf.sync(packageFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async undeployTheme(packageName: string): Promise<void> {
|
||||||
|
const packageFolder = Path.join(process.env.PWD, 'work', packageName);
|
||||||
|
rimraf.sync(packageFolder);
|
||||||
|
}
|
||||||
|
|
||||||
public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
||||||
return GuaribasPackage.create({
|
return GuaribasPackage.create({
|
||||||
|
@ -270,13 +272,13 @@ export class GBDeployer {
|
||||||
|
|
||||||
case '.gbkb':
|
case '.gbkb':
|
||||||
const service = new KBService(this.core.sequelize);
|
const service = new KBService(this.core.sequelize);
|
||||||
|
|
||||||
await service.deployKb(this.core, this, localPath);
|
await service.deployKb(this.core, this, localPath);
|
||||||
|
break;
|
||||||
|
|
||||||
case '.gbdialog':
|
case '.gbdialog':
|
||||||
const vm = new GBVMService();
|
const vm = new GBVMService();
|
||||||
|
|
||||||
await vm.loadDialogPackage(localPath, min, this.core, this);
|
await vm.loadDialogPackage(localPath, min, this.core, this);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
||||||
|
@ -300,13 +302,18 @@ export class GBDeployer {
|
||||||
|
|
||||||
case '.gbkb':
|
case '.gbkb':
|
||||||
const service = new KBService(this.core.sequelize);
|
const service = new KBService(this.core.sequelize);
|
||||||
|
|
||||||
return service.undeployKbFromStorage(instance, this, p.packageId);
|
return service.undeployKbFromStorage(instance, this, p.packageId);
|
||||||
|
|
||||||
case '.gbui':
|
case '.gbui':
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '.gbtheme':
|
||||||
|
this.undeployTheme(packageName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.gbdialog':
|
case '.gbdialog':
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -41,6 +41,7 @@ import fs = require('fs');
|
||||||
import urlJoin = require('url-join');
|
import urlJoin = require('url-join');
|
||||||
import { GuaribasInstance } from '../models/GBModel';
|
import { GuaribasInstance } from '../models/GBModel';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService';
|
||||||
|
import { GBServer } from '../../../src/app';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the importing of packages.
|
* Handles the importing of packages.
|
||||||
|
@ -70,7 +71,7 @@ export class GBImporter {
|
||||||
const settings = JSON.parse(fs.readFileSync(urlJoin(localPath, 'settings.json'), 'utf8'));
|
const settings = JSON.parse(fs.readFileSync(urlJoin(localPath, 'settings.json'), 'utf8'));
|
||||||
const servicesJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'services.json'), 'utf8'));
|
const servicesJson = JSON.parse(fs.readFileSync(urlJoin(localPath, 'services.json'), 'utf8'));
|
||||||
|
|
||||||
packageJson = { ...packageJson, ...settings, ...servicesJson };
|
packageJson = { ...GBServer.globals.bootInstance, ...packageJson, ...settings, ...servicesJson };
|
||||||
|
|
||||||
if (botId !== undefined) {
|
if (botId !== undefined) {
|
||||||
packageJson.botId = botId;
|
packageJson.botId = botId;
|
||||||
|
@ -81,7 +82,7 @@ export class GBImporter {
|
||||||
|
|
||||||
return this.core.saveInstance(instance);
|
return this.core.saveInstance(instance);
|
||||||
} else {
|
} else {
|
||||||
return GuaribasInstance.create(packageJson);
|
return await GuaribasInstance.create(packageJson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,16 @@ export class GBMinService {
|
||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const url = '/webhooks/whatsapp';
|
||||||
|
GBServer.globals.server.post(url, async (req, res) => {
|
||||||
|
const text = req.body.messages[0].body;
|
||||||
|
const from = req.body.messages[0].author.split('@')[0];
|
||||||
|
const fromName = req.body.messages[0].senderName;
|
||||||
|
|
||||||
|
let botId = 'subway-prd';
|
||||||
|
const min = GBServer.globals.minInstances.filter(p => p.botId === botId)[0];
|
||||||
|
(min as any).whatsAppDirectLine.received(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
instances.map(async instance => {
|
instances.map(async instance => {
|
||||||
|
@ -141,12 +151,15 @@ export class GBMinService {
|
||||||
|
|
||||||
const uiUrl = `/${botId}`;
|
const uiUrl = `/${botId}`;
|
||||||
removeRoute(GBServer.globals.server, uiUrl);
|
removeRoute(GBServer.globals.server, uiUrl);
|
||||||
|
|
||||||
|
GBServer.globals.minInstances = GBServer.globals.minInstances.filter(p => p.botId !== botId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async mountBot(instance: IGBInstance) {
|
public async mountBot(instance: IGBInstance) {
|
||||||
|
|
||||||
// Build bot adapter.
|
// Build bot adapter.
|
||||||
const { min, adapter, conversationState } = await this.buildBotAdapter(instance, GBServer.globals.publicAddress, GBServer.globals.sysPackages);
|
const { min, adapter, conversationState } = await this.buildBotAdapter(instance, GBServer.globals.publicAddress, GBServer.globals.sysPackages);
|
||||||
|
GBServer.globals.minInstances.push(min);
|
||||||
|
|
||||||
// Install default VBA module.
|
// Install default VBA module.
|
||||||
//this.deployer.deployPackage(min, 'packages/default.gbdialog');
|
//this.deployer.deployPackage(min, 'packages/default.gbdialog');
|
||||||
|
@ -359,12 +372,6 @@ export class GBMinService {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
sysPackages.forEach(e => {
|
sysPackages.forEach(e => {
|
||||||
e.loadBot(min);
|
e.loadBot(min);
|
||||||
if (index === 6) { // TODO: Remove this magic number and use a map.
|
|
||||||
const url = '/instances/:botId/whatsapp';
|
|
||||||
server.post(url, async (req, res) => {
|
|
||||||
await (e as any).channel.received(req, res);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
index++;
|
index++;
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
|
|
@ -66,9 +66,6 @@ export class AskDialog extends IGBDialog {
|
||||||
min.dialogs.add(new WaterfallDialog('/answerEvent', AskDialog.getAnswerEventDialog(service, min)));
|
min.dialogs.add(new WaterfallDialog('/answerEvent', AskDialog.getAnswerEventDialog(service, min)));
|
||||||
min.dialogs.add(new WaterfallDialog('/answer', AskDialog.getAnswerDialog(min, service)));
|
min.dialogs.add(new WaterfallDialog('/answer', AskDialog.getAnswerDialog(min, service)));
|
||||||
min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min)));
|
min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min)));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getAskDialog(min: GBMinInstance) {
|
private static getAskDialog(min: GBMinInstance) {
|
||||||
|
|
|
@ -46,13 +46,12 @@ import { WhatsappDirectLine } from './services/WhatsappDirectLine';
|
||||||
export class GBWhatsappPackage implements IGBPackage {
|
export class GBWhatsappPackage implements IGBPackage {
|
||||||
public sysPackages: IGBPackage[];
|
public sysPackages: IGBPackage[];
|
||||||
|
|
||||||
public channel: WhatsappDirectLine;
|
|
||||||
|
|
||||||
public loadBot(min: GBMinInstance): void {
|
public loadBot(min: GBMinInstance): void {
|
||||||
// Only loads engine if it is defined on services.json.
|
// Only loads engine if it is defined on services.json.
|
||||||
|
|
||||||
if (min.instance.whatsappBotKey !== undefined) {
|
if (min.instance.whatsappBotKey !== undefined) {
|
||||||
this.channel = new WhatsappDirectLine(
|
min.whatsAppDirectLine = new WhatsappDirectLine(
|
||||||
min.botId,
|
min.botId,
|
||||||
min.instance.whatsappBotKey,
|
min.instance.whatsappBotKey,
|
||||||
min.instance.whatsappServiceKey,
|
min.instance.whatsappServiceKey,
|
||||||
|
@ -62,9 +61,6 @@ export class GBWhatsappPackage implements IGBPackage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getChannel() {
|
|
||||||
return this.channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getDialogs(min: GBMinInstance) {
|
public getDialogs(min: GBMinInstance) {
|
||||||
GBLog.verbose(`getDialogs called.`);
|
GBLog.verbose(`getDialogs called.`);
|
||||||
|
|
|
@ -86,7 +86,7 @@ export class WhatsappDirectLine extends GBService {
|
||||||
url: urlJoin(this.whatsappServiceUrl, 'webhook'),
|
url: urlJoin(this.whatsappServiceUrl, 'webhook'),
|
||||||
qs: {
|
qs: {
|
||||||
token: this.whatsappServiceKey,
|
token: this.whatsappServiceKey,
|
||||||
webhookUrl: `${GBServer.globals.publicAddress}/instances/${this.botId}/whatsapp`,
|
webhookUrl: `${GBServer.globals.publicAddress}/webhooks/whatsapp`,
|
||||||
set: true
|
set: true
|
||||||
},
|
},
|
||||||
headers: {
|
headers: {
|
||||||
|
|
15
src/app.ts
15
src/app.ts
|
@ -49,8 +49,6 @@ import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer';
|
||||||
import { GBImporter } from '../packages/core.gbapp/services/GBImporterService';
|
import { GBImporter } from '../packages/core.gbapp/services/GBImporterService';
|
||||||
import { GBMinService } from '../packages/core.gbapp/services/GBMinService';
|
import { GBMinService } from '../packages/core.gbapp/services/GBMinService';
|
||||||
|
|
||||||
const appPackages: IGBPackage[] = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global shared server data;
|
* Global shared server data;
|
||||||
*/
|
*/
|
||||||
|
@ -61,6 +59,7 @@ export class RootData {
|
||||||
public appPackages: any[];
|
public appPackages: any[];
|
||||||
minService: GBMinService;
|
minService: GBMinService;
|
||||||
bootInstance: IGBInstance;
|
bootInstance: IGBInstance;
|
||||||
|
public minInstances: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,6 +80,10 @@ export class GBServer {
|
||||||
const port = GBConfigService.getServerPort();
|
const port = GBConfigService.getServerPort();
|
||||||
const server = express();
|
const server = express();
|
||||||
GBServer.globals.server = server;
|
GBServer.globals.server = server;
|
||||||
|
GBServer.globals.appPackages = [];
|
||||||
|
GBServer.globals.sysPackages = [];
|
||||||
|
GBServer.globals.minInstances = [];
|
||||||
|
|
||||||
server.use(bodyParser.json());
|
server.use(bodyParser.json());
|
||||||
server.use(bodyParser.urlencoded({ extended: true }));
|
server.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
@ -92,7 +95,6 @@ export class GBServer {
|
||||||
// Reads basic configuration, initialize minimal services.
|
// Reads basic configuration, initialize minimal services.
|
||||||
|
|
||||||
const core: IGBCoreService = new GBCoreService();
|
const core: IGBCoreService = new GBCoreService();
|
||||||
|
|
||||||
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);
|
||||||
|
@ -118,7 +120,6 @@ export class GBServer {
|
||||||
|
|
||||||
// Creates a boot instance or load it from storage.
|
// Creates a boot instance or load it from storage.
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await core.initStorage();
|
await core.initStorage();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -132,11 +133,9 @@ export class GBServer {
|
||||||
// Deploys system and user packages.
|
// Deploys system and user packages.
|
||||||
|
|
||||||
GBLog.info(`Deploying packages...`);
|
GBLog.info(`Deploying packages...`);
|
||||||
const sysPackages = core.loadSysPackages(core);
|
GBServer.globals.sysPackages = core.loadSysPackages(core);
|
||||||
await core.checkStorage(azureDeployer);
|
await core.checkStorage(azureDeployer);
|
||||||
await deployer.deployPackages(core, server, appPackages);
|
await deployer.deployPackages(core, server, GBServer.globals.appPackages);
|
||||||
GBServer.globals.sysPackages = sysPackages;
|
|
||||||
GBServer.globals.appPackages = appPackages;
|
|
||||||
|
|
||||||
// Loads boot bot and other instances.
|
// Loads boot bot and other instances.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue