Merge pull request #96 from rodrigorodriguez/master

Removing POC code and Whatsapp
This commit is contained in:
Rodrigo Rodriguez 2019-05-23 22:37:59 -03:00 committed by GitHub
commit 87460fc9ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 6695 additions and 5978 deletions

View file

@ -5,5 +5,4 @@
"arrowParens": "avoid", "arrowParens": "avoid",
"semi": true, "semi": true,
"singleQuote": true "singleQuote": true
} }

1655
directline-3.0.json Normal file

File diff suppressed because one or more lines are too long

10510
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
"Jorge Ramos <jramos@pobox.com>" "Jorge Ramos <jramos@pobox.com>"
], ],
"engines": { "engines": {
"node": "=10.13.0" "node": "=10.15.2"
}, },
"license": "AGPL-3.0", "license": "AGPL-3.0",
"preferGlobal": true, "preferGlobal": true,
@ -47,90 +47,90 @@
"commit": "git-cz" "commit": "git-cz"
}, },
"dependencies": { "dependencies": {
"@microsoft/microsoft-graph-client": "1.5.2", "@microsoft/microsoft-graph-client": "1.6.0",
"@semantic-release/exec": "^3.3.2", "@semantic-release/exec": "3.3.2",
"adal-node": "0.1.28", "adal-node": "0.1.28",
"async": "2.6.2", "async": "2.6.2",
"async-promises": "0.2.1", "async-promises": "0.2.2",
"azure-arm-cognitiveservices": "2.4.1", "azure-arm-cognitiveservices": "3.0.0",
"azure-arm-resource": "7.3.0", "azure-arm-resource": "7.3.0",
"azure-arm-search": "^1.3.0-preview", "azure-arm-search": "1.3.0-preview",
"azure-arm-sql": "5.6.0", "azure-arm-sql": "5.7.0",
"azure-arm-website": "5.7.0", "azure-arm-website": "5.7.0",
"bluebird": "^3.5.4", "bluebird": "3.5.4",
"body-parser": "1.18.3", "body-parser": "1.19.0",
"botbuilder": "4.3.4", "botbuilder": "4.4.0",
"botbuilder-ai": "4.3.4", "botbuilder-ai": "4.4.0",
"botbuilder-azure": "4.3.4", "botbuilder-azure": "4.4.0",
"botbuilder-choices": "4.0.0-preview1.2", "botbuilder-choices": "4.0.0-preview1.2",
"botbuilder-dialogs": "4.3.4", "botbuilder-dialogs": "4.4.0",
"botbuilder-prompts": "4.0.0-preview1.2", "botbuilder-prompts": "4.0.0-preview1.2",
"botlib": "0.1.24", "botlib": "1.2.0",
"chai": "4.2.0", "chai": "4.2.0",
"child_process": "^1.0.2", "child_process": "1.0.2",
"chokidar": "2.1.5", "chokidar": "3.0.0",
"cli-spinner": "^0.2.10", "cli-spinner": "0.2.10",
"csv-parse": "4.3.4", "csv-parse": "4.4.1",
"dotenv-extended": "2.4.0", "dotenv-extended": "2.4.0",
"express": "4.16.4", "express": "4.16.4",
"express-promise-router": "3.0.3", "express-promise-router": "3.0.3",
"fs-extra": "7.0.1", "fs-extra": "8.0.0",
"ip": "^1.1.5", "ip": "1.1.5",
"js-beautify": "^1.9.1", "js-beautify": "1.10.0",
"localize": "0.4.7", "localize": "0.4.7",
"marked": "0.6.2", "marked": "0.6.2",
"mocha": "6.0.2", "mocha": "6.1.4",
"mocha-typescript": "1.1.17", "mocha-typescript": "1.1.17",
"ms": "2.1.1", "ms": "2.1.1",
"ms-rest-azure": "2.6.0", "ms-rest-azure": "2.6.0",
"ms-rest-js": "^1.0.1", "ms-rest-js": "1.0.1",
"nexmo": "2.4.1", "nexmo": "2.4.1",
"ngrok": "3.1.1", "ngrok": "3.1.1",
"nyc": "13.3.0", "nyc": "14.1.1",
"opn": "6.0.0", "opn": "6.0.0",
"pragmatismo-io-framework": "1.0.19", "pragmatismo-io-framework": "1.0.19",
"process-exists": "3.1.0", "process-exists": "3.1.0",
"public-ip": "^3.0.0", "public-ip": "3.1.0",
"reflect-metadata": "0.1.13", "reflect-metadata": "0.1.13",
"request-promise": "4.2.4", "request-promise": "4.2.4",
"request-promise-native": "1.0.7", "request-promise-native": "1.0.7",
"scanf": "^1.0.2", "scanf": "1.0.2",
"sequelize": "^5.2.12", "sequelize": "5.8.6",
"sequelize-typescript": "0.6.9", "sequelize-typescript": "0.6.10",
"shx": "0.3.2", "shx": "0.3.2",
"simple-git": "1.110.0", "simple-git": "1.113.0",
"sqlite3": "4.0.6", "sqlite3": "4.0.8",
"strict-password-generator": "^1.1.2", "strict-password-generator": "1.1.2",
"swagger-client": "3.8.25", "swagger-client": "^2.1.18",
"tedious": "6.1.0", "tedious": "6.1.1",
"temperature-js": "^0.1.0", "temperature-js": "0.1.0",
"ts-node": "8.0.3", "ts-node": "8.1.0",
"typedoc": "0.14.2", "typedoc": "0.14.2",
"typedoc-plugin-external-module-name": "^2.0.0", "typedoc-plugin-external-module-name": "2.1.0",
"typedoc-plugin-markdown": "^1.1.27", "typedoc-plugin-markdown": "1.2.0",
"typescript": "3.4.1", "typescript": "3.4.5",
"url-join": "4.0.0", "url-join": "4.0.0",
"vbscript-to-typescript": "^1.0.8", "vbscript-to-typescript": "1.0.8",
"wait-until": "0.0.2", "wait-until": "0.0.2",
"walk-promise": "0.2.0", "walk-promise": "0.2.0",
"winston": "3.2.1" "winston": "3.2.1"
}, },
"devDependencies": { "devDependencies": {
"@semantic-release/changelog": "^3.0.2", "@semantic-release/changelog": "3.0.2",
"@semantic-release/commit-analyzer": "^6.1.0", "@semantic-release/commit-analyzer": "6.1.0",
"@semantic-release/git": "^7.0.8", "@semantic-release/git": "7.0.8",
"@semantic-release/github": "^5.2.10", "@semantic-release/github": "5.2.10",
"@semantic-release/npm": "^5.1.4", "@semantic-release/npm": "5.1.7",
"@semantic-release/release-notes-generator": "^7.1.4", "@semantic-release/release-notes-generator": "7.1.4",
"@types/chai": "4.1.7", "@types/chai": "4.1.7",
"@types/mocha": "5.2.6", "@types/mocha": "5.2.6",
"@types/sequelize": "4.27.46", "@types/sequelize": "4.27.49",
"@types/url-join": "4.0.0", "@types/url-join": "4.0.0",
"@types/winston": "2.4.4", "@types/winston": "2.4.4",
"ban-sensitive-files": "1.9.2", "ban-sensitive-files": "1.9.2",
"commitizen": "^3.0.7", "commitizen": "3.1.1",
"coveralls": "^3.0.3", "coveralls": "3.0.3",
"cz-conventional-changelog": "^2.1.0", "cz-conventional-changelog": "2.1.0",
"dependency-check": "3.3.0", "dependency-check": "3.3.0",
"deps-ok": "1.4.1", "deps-ok": "1.4.1",
"git-issues": "1.3.1", "git-issues": "1.3.1",
@ -138,12 +138,12 @@
"nsp": "3.2.1", "nsp": "3.2.1",
"pre-git": "3.17.1", "pre-git": "3.17.1",
"prettier-standard": "9.1.1", "prettier-standard": "9.1.1",
"semantic-release": "^15.13.3", "semantic-release": "15.13.12",
"standard": "12.0.1", "standard": "12.0.1",
"travis-deploy-once": "5.0.11", "travis-deploy-once": "5.0.11",
"ts-loader": "^5.3.3", "ts-loader": "6.0.0",
"tslint": "^5.15.0", "tslint": "5.16.0",
"tslint-microsoft-contrib": "^6.1.0" "tslint-microsoft-contrib": "6.1.1"
}, },
"eslintConfig": { "eslintConfig": {
"env": { "env": {

View file

@ -36,6 +36,7 @@
'use strict'; 'use strict';
var crypto = require('crypto')
import { WaterfallDialog } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
import { GBMinInstance, IGBDialog } from 'botlib'; import { GBMinInstance, IGBDialog } from 'botlib';
import urlJoin = require('url-join'); import urlJoin = require('url-join');

View file

@ -201,6 +201,36 @@ export class AzureDeployerService implements IGBInstallationDeployer {
}; };
} }
public async botExists(botId, group, endpoint) {
const baseUrl = `https://management.azure.com/`;
const username = GBConfigService.get('CLOUD_USERNAME');
const password = GBConfigService.get('CLOUD_PASSWORD');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
const httpClient = new ServiceClient();
const parameters = {
properties: {
endpoint: endpoint
}
};
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=${this.apiVersion}`;
const url = urlJoin(baseUrl, query);
const req = AzureDeployerService.createRequestObject(url, accessToken, 'GET', JSON.stringify(parameters));
const res = await httpClient.sendRequest(req);
// CHECK
if (!JSON.parse(res.bodyAsText).id) {
return false;
} else {
return true;
}
}
public async updateBotProxy(botId, group, endpoint) { public async updateBotProxy(botId, group, endpoint) {
const baseUrl = `https://management.azure.com/`; const baseUrl = `https://management.azure.com/`;
const username = GBConfigService.get('CLOUD_USERNAME'); const username = GBConfigService.get('CLOUD_USERNAME');
@ -229,6 +259,38 @@ export class AzureDeployerService implements IGBInstallationDeployer {
GBLog.info(`Bot proxy updated at: ${endpoint}.`); GBLog.info(`Bot proxy updated at: ${endpoint}.`);
} }
public async updateBot(botId: string, group: string, name: string,
description: string, endpoint: string, iconUrl: string) {
const baseUrl = `https://management.azure.com/`;
const username = GBConfigService.get('CLOUD_USERNAME');
const password = GBConfigService.get('CLOUD_PASSWORD');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
const httpClient = new ServiceClient();
const parameters = {
properties: {
description: description,
displayName: name,
endpoint: endpoint,
iconUrl: iconUrl
}
};
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=${this.apiVersion}`;
const url = urlJoin(baseUrl, query);
const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
const res = await httpClient.sendRequest(req);
// CHECK
if (!JSON.parse(res.bodyAsText).id) {
throw res.bodyAsText;
}
GBLog.info(`Bot proxy updated at: ${endpoint}.`);
}
public async openStorageFirewall(groupName, serverName) { public async openStorageFirewall(groupName, serverName) {
const username = GBConfigService.get('CLOUD_USERNAME'); const username = GBConfigService.get('CLOUD_USERNAME');
const password = GBConfigService.get('CLOUD_PASSWORD'); const password = GBConfigService.get('CLOUD_PASSWORD');
@ -296,7 +358,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
instance.searchIndex = 'azuresql-index'; instance.searchIndex = 'azuresql-index';
instance.searchIndexer = 'azuresql-indexer'; instance.searchIndexer = 'azuresql-indexer';
instance.searchKey = searchKeys.primaryKey; instance.searchKey = searchKeys.primaryKey;
this.deployer.rebuildIndex(instance, this.deployer); this.deployer.rebuildIndex(instance, this.getKBSearchSchema(instance.searchIndex));
GBLog.info(`Deploying Speech...`); GBLog.info(`Deploying Speech...`);
const speech = await this.createSpeech(name, `${name}-speech`, instance.cloudLocation); const speech = await this.createSpeech(name, `${name}-speech`, instance.cloudLocation);
@ -378,43 +440,10 @@ export class AzureDeployerService implements IGBInstallationDeployer {
this.deployFarm(url, instance, credentials, subscriptionId); this.deployFarm(url, instance, credentials, subscriptionId);
} }
private initServices(credentials: any, subscriptionId: string) {
this.resourceClient = new ResourceManagementClient.default(credentials, subscriptionId);
this.webSiteClient = new WebSiteManagementClient(credentials, subscriptionId);
this.storageClient = new SqlManagementClient(credentials, subscriptionId);
this.cognitiveClient = new CognitiveServicesManagementClient(credentials, subscriptionId);
this.searchClient = new SearchManagementClient(credentials, subscriptionId);
this.accessToken = credentials.tokenCache._entries[0].accessToken;
}
private async createStorageServer(group, name, administratorLogin, administratorPassword, serverName, location) {
const params = {
location: location,
administratorLogin: administratorLogin,
administratorLoginPassword: administratorPassword,
fullyQualifiedDomainName: `${serverName}.database.windows.net`
};
return this.storageClient.servers.createOrUpdate(group, name, params);
}
private async registerProviders(subscriptionId, baseUrl, accessToken) {
const query = `subscriptions/${subscriptionId}/providers/${this.provider}/register?api-version=2018-02-01`;
const requestUrl = urlJoin(baseUrl, query);
const req = new WebResource();
req.method = 'POST';
req.url = requestUrl;
req.headers = <any>{};
req.headers['Content-Type'] = 'application/json; charset=utf-8';
req.headers['accept-language'] = '*';
(req.headers as any).Authorization = `Bearer ${accessToken}`;
}
/** /**
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json * @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json
*/ */
private async internalDeployBot( public async internalDeployBot(
instance, instance,
accessToken, accessToken,
botId, botId,
@ -490,6 +519,39 @@ export class AzureDeployerService implements IGBInstallationDeployer {
}); });
} }
private initServices(credentials: any, subscriptionId: string) {
this.resourceClient = new ResourceManagementClient.default(credentials, subscriptionId);
this.webSiteClient = new WebSiteManagementClient(credentials, subscriptionId);
this.storageClient = new SqlManagementClient(credentials, subscriptionId);
this.cognitiveClient = new CognitiveServicesManagementClient(credentials, subscriptionId);
this.searchClient = new SearchManagementClient(credentials, subscriptionId);
this.accessToken = credentials.tokenCache._entries[0].accessToken;
}
private async createStorageServer(group, name, administratorLogin, administratorPassword, serverName, location) {
const params = {
location: location,
administratorLogin: administratorLogin,
administratorLoginPassword: administratorPassword,
fullyQualifiedDomainName: `${serverName}.database.windows.net`
};
return this.storageClient.servers.createOrUpdate(group, name, params);
}
private async registerProviders(subscriptionId, baseUrl, accessToken) {
const query = `subscriptions/${subscriptionId}/providers/${this.provider}/register?api-version=2018-02-01`;
const requestUrl = urlJoin(baseUrl, query);
const req = new WebResource();
req.method = 'POST';
req.url = requestUrl;
req.headers = <any>{};
req.headers['Content-Type'] = 'application/json; charset=utf-8';
req.headers['accept-language'] = '*';
(req.headers as any).Authorization = `Bearer ${accessToken}`;
}
private async createNLPService( private async createNLPService(
name: string, name: string,
description: string, description: string,

View file

@ -35,6 +35,7 @@
import { TurnContext } from 'botbuilder'; import { TurnContext } from 'botbuilder';
import { WaterfallStepContext } from 'botbuilder-dialogs'; import { WaterfallStepContext } from 'botbuilder-dialogs';
import { GBLog, GBMinInstance } from 'botlib'; import { GBLog, GBMinInstance } from 'botlib';
import * as crypto from 'crypto';
import * as request from 'request-promise-native'; import * as request from 'request-promise-native';
import urlJoin = require('url-join'); import urlJoin = require('url-join');
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
@ -104,7 +105,7 @@ class SysClass {
public async httpGet(url: string, qs) { public async httpGet(url: string, qs) {
const options = { const options = {
uri: urlJoin(url , qs) uri: urlJoin(url, qs)
}; };
return request.get(options); return request.get(options);
@ -132,7 +133,10 @@ export class DialogClass {
} }
public async hear(cb) { public async hear(cb) {
const idCallback = crypto.getRandomValues(new Uint32Array(16))[0]; function random(low, high) {
return Math.random() * (high - low) + low
}
const idCallback = random(0, 120000000);
this.min.cbMap[idCallback] = cb; this.min.cbMap[idCallback] = cb;
await this.step.beginDialog('/hear', { id: idCallback }); await this.step.beginDialog('/hear', { id: idCallback });
} }

View file

@ -43,12 +43,12 @@ import { GBLog } from 'botlib';
*/ */
export class GBConfigService { export class GBConfigService {
public static getServerPort(): number { public static getServerPort(): number {
if (process.env.port !== undefined) { if (process.env.PORT) {
return Number(process.env.port);
}
if (process.env.PORT !== undefined) {
return Number(process.env.PORT); return Number(process.env.PORT);
} }
if (process.env.port) {
return Number(process.env.port);
}
return 4242; return 4242;
} }
@ -102,6 +102,9 @@ export class GBConfigService {
case 'STORAGE_STORAGE': case 'STORAGE_STORAGE':
value = './guaribas.sqlite'; value = './guaribas.sqlite';
break; break;
case 'GBKB_AUTO_DEPLOY':
value = false;
break;
case 'ADDITIONAL_DEPLOY_PATH': case 'ADDITIONAL_DEPLOY_PATH':
value = undefined; value = undefined;
break; break;

View file

@ -347,8 +347,8 @@ STORAGE_SYNC=true
GBCorePackage, GBCorePackage,
GBSecurityPackage, GBSecurityPackage,
GBKBPackage, GBKBPackage,
GBCustomerSatisfactionPackage GBCustomerSatisfactionPackage,
// GBWhatsappPackage GBWhatsappPackage
].forEach(e => { ].forEach(e => {
GBLog.info(`Loading sys package: ${e.name}...`); GBLog.info(`Loading sys package: ${e.name}...`);
const p = Object.create(e.prototype) as IGBPackage; const p = Object.create(e.prototype) as IGBPackage;

View file

@ -46,8 +46,10 @@ const graph = require('@microsoft/microsoft-graph-client');
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';
import { GuaribasPackage } from '../models/GBModel'; import { GBServer } from '../../../src/app';
import { GuaribasPackage, GuaribasInstance } from '../models/GBModel';
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService'; import { GBAdminService } from './../../admin.gbapp/services/GBAdminService';
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService';
import { KBService } from './../../kb.gbapp/services/KBService'; import { KBService } from './../../kb.gbapp/services/KBService';
import { GBConfigService } from './GBConfigService'; import { GBConfigService } from './GBConfigService';
import { GBImporter } from './GBImporterService'; import { GBImporter } from './GBImporterService';
@ -70,9 +72,13 @@ export class GBDeployer {
} }
public static getConnectionStringFromInstance(instance: IGBInstance) { public static getConnectionStringFromInstance(instance: IGBInstance) {
return `Server=tcp:torageServer}.database.windows.net,1433;Database=${instance.storageName};User ID=${ return `Server=tcp:${instance.storageServer}.database.windows.net,1433;Database=${
instance.storageName
};User ID=${
instance.storageUsername instance.storageUsername
};Password=${instance.storagePassword};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`; };Password=${
instance.storagePassword
};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`;
} }
/** /**
@ -85,6 +91,7 @@ export class GBDeployer {
return new Promise( return new Promise(
(resolve: any, reject: any): any => { (resolve: any, reject: any): any => {
GBLog.info(`PWD ${process.env.PWD}...`);
let totalPackages = 0; let totalPackages = 0;
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH'); const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
let paths = [GBDeployer.deployFolder]; let paths = [GBDeployer.deployFolder];
@ -139,6 +146,7 @@ export class GBDeployer {
GBLog.info(`App Package deployment done.`); GBLog.info(`App Package deployment done.`);
({ generalPackages, totalPackages } = await this.deployDataPackages( ({ generalPackages, totalPackages } = await this.deployDataPackages(
core, core,
botPackages, botPackages,
_this, _this,
@ -157,10 +165,47 @@ export class GBDeployer {
* Deploys a bot to the storage. * Deploys a bot to the storage.
*/ */
public async deployBot(localPath: string): Promise<IGBInstance> { public async deployBot(localPath: string, proxyAddress: string): Promise<void> {
const packageName = Path.basename(localPath); const packageName = Path.basename(localPath);
return await this.importer.importIfNotExistsBotPackage(undefined, packageName, localPath); const service = new AzureDeployerService(this);
let instance = await this.importer.importIfNotExistsBotPackage(undefined, packageName, localPath);
const username = GBConfigService.get('CLOUD_USERNAME');
const password = GBConfigService.get('CLOUD_PASSWORD');
const group = GBConfigService.get('CLOUD_GROUP');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
if (await service.botExists(instance.botId, group, proxyAddress)) {
instance = await service.updateBot(
instance,
accessToken,
instance.title,
instance.description,
proxyAddress,
''
);
} else {
instance = await service.internalDeployBot(
instance,
accessToken,
instance.botId,
instance.title,
group,
instance.description,
`${proxyAddress}/api/messages/${instance.botId}`,
'global',
instance.nlpAppId,
instance.nlpKey,
instance.marketplaceId,
instance.marketplacePassword,
subscriptionId
);
}
await this.core.saveInstance(instance);
} }
public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> { public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> {
@ -188,17 +233,17 @@ export class GBDeployer {
switch (packageType) { switch (packageType) {
case '.gbot': case '.gbot':
return this.deployBot(localPath); await this.deployBot(localPath, min.proxyAddress);
case '.gbkb': case '.gbkb':
const service = new KBService(this.core.sequelize); const service = new KBService(this.core.sequelize);
return service.deployKb(this.core, this, localPath); await service.deployKb(this.core, this, localPath);
case '.gbdialog': case '.gbdialog':
const vm = new GBVMService(); const vm = new GBVMService();
return vm.loadDialogPackage(localPath, min, this.core, this); await vm.loadDialogPackage(localPath, min, this.core, this);
default: default:
const err = GBError.create(`Unhandled package type: ${packageType}.`); const err = GBError.create(`Unhandled package type: ${packageType}.`);
@ -284,6 +329,7 @@ export class GBDeployer {
} }
private async deployDataPackages( private async deployDataPackages(
core: IGBCoreService, core: IGBCoreService,
botPackages: string[], botPackages: string[],
_this: this, _this: this,
@ -301,10 +347,10 @@ export class GBDeployer {
// Deploys all .gbot files first. // Deploys all .gbot files first.
botPackages.forEach(e => { botPackages.forEach(async (e) => {
if (e !== 'packages\\boot.gbot') { if (e !== 'packages\\boot.gbot') {
GBLog.info(`Deploying bot: ${e}...`); GBLog.info(`Deploying bot: ${e}...`);
_this.deployBot(e); await _this.deployBot(e, GBServer.globals.proxyAddress);
GBLog.info(`Bot: ${e} deployed...`); GBLog.info(`Bot: ${e} deployed...`);
} }
}); });
@ -330,6 +376,8 @@ export class GBDeployer {
// Already Handled // Already Handled
} else if (Path.extname(filename) === '.gbdialog') { } else if (Path.extname(filename) === '.gbdialog') {
// Already Handled // Already Handled
} else if (Path.extname(filename) === '.gbignore') {
// Ignored
} else { } else {
// Unknown package format. // Unknown package format.
const err = new Error(`Package type not handled: ${filename}.`); const err = new Error(`Package type not handled: ${filename}.`);

View file

@ -36,7 +36,7 @@
'use strict'; 'use strict';
import { IGBCoreService } from 'botlib'; import { IGBCoreService, IGBInstance } from 'botlib';
import fs = require('fs'); import fs = require('fs');
import urlJoin = require('url-join'); import urlJoin = require('url-join');
import { GuaribasInstance } from '../models/GBModel'; import { GuaribasInstance } from '../models/GBModel';
@ -57,14 +57,12 @@ export class GBImporter {
botId = packageJson.botId; botId = packageJson.botId;
} }
const instance = await this.core.loadInstance(botId); const instance = await this.core.loadInstance(botId);
if (instance !== null) {
return instance; return await this.createOrUpdateInstanceInternal(instance, botId, localPath, packageJson);
} else {
return await this.createInstanceInternal(botId, localPath, packageJson);
}
} }
private async createInstanceInternal(botId: string, localPath: string, packageJson: any) { private async createOrUpdateInstanceInternal(instance: IGBInstance,
botId: string, localPath: string, packageJson: any) {
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'));
@ -74,6 +72,12 @@ export class GBImporter {
packageJson.botId = botId; packageJson.botId = botId;
} }
if (instance !== null) {
instance = { ...instance, ...packageJson, ...settings, ...servicesJson };
return this.core.saveInstance(instance);
} else {
return GuaribasInstance.create(packageJson); return GuaribasInstance.create(packageJson);
} }
}
} }

View file

@ -112,7 +112,8 @@ export class GBMinService {
server: any, server: any,
appPackages: IGBPackage[], appPackages: IGBPackage[],
instances: IGBInstance[], instances: IGBInstance[],
deployer: GBDeployer deployer: GBDeployer,
proxyAddress: string
) { ) {
// Serves default UI on root address '/'. // Serves default UI on root address '/'.
@ -136,11 +137,11 @@ export class GBMinService {
// Build bot adapter. // Build bot adapter.
const { min, adapter, conversationState } = await this.buildBotAdapter(instance); const { min, adapter, conversationState } = await this.buildBotAdapter(instance, proxyAddress);
// Install default VBA module. // Install default VBA module.
// DISABLED: deployer.deployPackage(min, 'packages/default.gbdialog'); deployer.deployPackage(min, 'packages/default.gbdialog');
// Call the loadBot context.activity for all packages. // Call the loadBot context.activity for all packages.
@ -234,8 +235,8 @@ export class GBMinService {
botId = bootInstance.botId; botId = bootInstance.botId;
} }
const instance = await this.core.loadInstance(botId); const instance = await this.core.loadInstance(botId);
if (instance !== undefined) { if (instance !== null) {
const speechToken = await this.getSTSToken(instance); const speechToken = instance.speechKey != null ? await this.getSTSToken(instance) : null;
let theme = instance.theme; let theme = instance.theme;
if (theme !== undefined) { if (theme !== undefined) {
theme = 'default.gbtheme'; theme = 'default.gbtheme';
@ -312,7 +313,7 @@ export class GBMinService {
} }
} }
private async buildBotAdapter(instance: any) { private async buildBotAdapter(instance: any, proxyAddress: string) {
const adapter = new BotFrameworkAdapter({ const adapter = new BotFrameworkAdapter({
appId: instance.marketplaceId, appId: instance.marketplaceId,
appPassword: instance.marketplacePassword appPassword: instance.marketplacePassword
@ -335,6 +336,7 @@ export class GBMinService {
min.instance = await this.core.loadInstance(min.botId); min.instance = await this.core.loadInstance(min.botId);
min.cbMap = {}; min.cbMap = {};
min.scriptMap = {}; min.scriptMap = {};
min.sandBoxMap = {};
min.userProfile = conversationState.createProperty('userProfile'); min.userProfile = conversationState.createProperty('userProfile');
const dialogState = conversationState.createProperty('dialogState'); const dialogState = conversationState.createProperty('dialogState');
@ -346,7 +348,7 @@ export class GBMinService {
} }
private invokeLoadBot(appPackages: any[], min: GBMinInstance, server: any) { private invokeLoadBot(appPackages: any[], min: GBMinInstance, server: any) {
const sysPackages : IGBPackage[] = []; const sysPackages: IGBPackage[] = [];
// NOTE: A semicolon is necessary before this line. // NOTE: A semicolon is necessary before this line.
[ [
GBCorePackage, GBCorePackage,
@ -354,8 +356,8 @@ export class GBMinService {
GBAdminPackage, GBAdminPackage,
GBKBPackage, GBKBPackage,
GBAnalyticsPackage, GBAnalyticsPackage,
GBCustomerSatisfactionPackage GBCustomerSatisfactionPackage,
// DISABLED: GBWhatsappPackage GBWhatsappPackage
].forEach(sysPackage => { ].forEach(sysPackage => {
const p = Object.create(sysPackage.prototype) as IGBPackage; const p = Object.create(sysPackage.prototype) as IGBPackage;
p.loadBot(min); p.loadBot(min);
@ -395,7 +397,7 @@ export class GBMinService {
await adapter.processActivity(req, res, async context => { await adapter.processActivity(req, res, async context => {
// Get loaded user state // Get loaded user state
const step = await min.dialogs.createContext(context); const step = await min.dialogs.createContext(context);
step.context.activity.locale = 'en-US'; step.context.activity.locale = 'pt-BR';
try { try {
const user = await min.userProfile.get(context, {}); const user = await min.userProfile.get(context, {});

View file

@ -163,9 +163,9 @@ export class GBVMService extends GBService {
let parsedCode = code; let parsedCode = code;
const hearExp = /(\w+).*hear.*\(\)/; const hearExp = /(\w+).*hear.*\(\)/;
let match1 = hearExp.exec(code); let match1;
while (match1 !== undefined) { while ((match1 = hearExp.exec(code))) {
let pos = 0; let pos = 0;
// Writes async body. // Writes async body.
@ -185,9 +185,8 @@ export class GBVMService extends GBService {
let right = 0; let right = 0;
let left = 1; let left = 1;
let match2 = /\{|\}/.exec(tempCode); let match2;
while ((match2 = /\{|\}/.exec(tempCode))) {
while (match2 !== undefined) {
const c = tempCode.substring(match2.index, match2.index + 1); const c = tempCode.substring(match2.index, match2.index + 1);
if (c === '}') { if (c === '}') {
@ -202,7 +201,6 @@ export class GBVMService extends GBService {
if (left === right) { if (left === right) {
break; break;
} }
match1 = hearExp.exec(code);
} }
parsedCode += code.substring(start + match1[0].length + 1, pos + match1[0].length); parsedCode += code.substring(start + match1[0].length + 1, pos + match1[0].length);
@ -212,12 +210,11 @@ export class GBVMService extends GBService {
// A interaction will be made for each hear. // A interaction will be made for each hear.
code = parsedCode; code = parsedCode;
match2 = /\{|\}/.exec(tempCode);
} }
parsedCode = this.handleThisAndAwait(parsedCode); parsedCode = this.handleThisAndAwait(parsedCode);
parsedCode = beautify(parsedCode, { indent_size: 2, space_in_empty_paren: true }); parsedCode = beautify(parsedCode, { indent_size: 2, space_in_empty_paren: true })
fs.writeFileSync(jsfile, parsedCode); fs.writeFileSync(jsfile, parsedCode);
const sandbox: DialogClass = new DialogClass(min, deployer); const sandbox: DialogClass = new DialogClass(min, deployer);
@ -225,6 +222,7 @@ export class GBVMService extends GBService {
vm.runInContext(parsedCode, context); vm.runInContext(parsedCode, context);
min.sandBoxMap[mainName] = sandbox; min.sandBoxMap[mainName] = sandbox;
GBLog.info(`[GBVMService] Finished loading of ${filename}`); GBLog.info(`[GBVMService] Finished loading of ${filename}`);
} }
} }
@ -259,16 +257,11 @@ export class GBVMService extends GBService {
return await step.prompt('textPrompt', {}); return await step.prompt('textPrompt', {});
}, },
async step => { async step => {
min.sandbox.context = step.context;
min.sandbox.step = step;
const cbId = step.activeDialog.state.cbId; const cbId = step.activeDialog.state.cbId;
const cb = min.cbMap[cbId]; const cb = min.cbMap[cbId];
cb.bind({ step: step, context: step.context }); cb.bind({ step: step, context: step.context });
await cb(step.result);
await step.endDialog(); return await step.next();
return await cb(step.result);
} }
]) ])
); );

View file

@ -66,6 +66,9 @@ 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) {
@ -194,4 +197,3 @@ export class AskDialog extends IGBDialog {
} }
]; ];
} }
}

View file

@ -58,7 +58,7 @@ export class GBWhatsappPackage implements IGBPackage {
min.instance.whatsappServiceKey, min.instance.whatsappServiceKey,
min.instance.whatsappServiceNumber, min.instance.whatsappServiceNumber,
min.instance.whatsappServiceUrl, min.instance.whatsappServiceUrl,
min.instance.whatsappServiceWebhookUrl min.instance.botId
); );
} }
} }

View file

@ -4,6 +4,7 @@ const Swagger = require('swagger-client');
const rp = require('request-promise'); const rp = require('request-promise');
import { GBLog, GBService } from 'botlib'; import { GBLog, GBService } from 'botlib';
import * as request from 'request-promise-native'; import * as request from 'request-promise-native';
import { GBServer } from '../../../src/app';
/** /**
* Support for Whatsapp. * Support for Whatsapp.
@ -11,7 +12,6 @@ import * as request from 'request-promise-native';
export class WhatsappDirectLine extends GBService { export class WhatsappDirectLine extends GBService {
public pollInterval = 1000; public pollInterval = 1000;
public directLineClientName = 'DirectLineClient'; public directLineClientName = 'DirectLineClient';
public directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json';
public directLineClient: any; public directLineClient: any;
public whatsappServiceKey: string; public whatsappServiceKey: string;
@ -38,15 +38,16 @@ export class WhatsappDirectLine extends GBService {
this.whatsappServiceNumber = whatsappServiceNumber; this.whatsappServiceNumber = whatsappServiceNumber;
this.whatsappServiceUrl = whatsappServiceUrl; this.whatsappServiceUrl = whatsappServiceUrl;
this.whatsappServiceWebhookUrl = whatsappServiceWebhookUrl; this.whatsappServiceWebhookUrl = whatsappServiceWebhookUrl;
var fs = require('fs')
this.directLineClient = rp(this.directLineSpecUrl) this.directLineClient =
.then(spec => { new Swagger({
return new Swagger({ spec: JSON.parse(fs.readFileSync('directline-3.0.json', 'utf8')),
spec: JSON.parse(spec.trim()),
usePromise: true usePromise: true
}); });
}) this.directLineClient
.then(async client => { .then(async client => {
client.clientAuthorizations.add( client.clientAuthorizations.add(
'AuthorizationBotConnector', 'AuthorizationBotConnector',
new Swagger.ApiKeyAuthorization('Authorization', `Bearer ${directLineSecret}`, 'header') new Swagger.ApiKeyAuthorization('Authorization', `Bearer ${directLineSecret}`, 'header')
@ -57,7 +58,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: `${this.whatsappServiceWebhookUrl}/instances/${this.botId}/whatsapp`, webhookUrl: `${GBServer.globals.proxyAddress}/instances/${this.botId}/whatsapp`,
set: true set: true
}, },
headers: { headers: {
@ -71,11 +72,6 @@ export class WhatsappDirectLine extends GBService {
} catch (error) { } catch (error) {
GBLog.error(`Error initializing 3rd party Whatsapp provider(1) ${error}`); GBLog.error(`Error initializing 3rd party Whatsapp provider(1) ${error}`);
} }
return client;
})
.catch(err => {
GBLog.error(`Error initializing 3rd party Whatsapp provider(2) ${err}`);
}); });
} }
@ -157,7 +153,7 @@ export class WhatsappDirectLine extends GBService {
if (activities && activities.length) { if (activities && activities.length) {
// Ignore own messages. // Ignore own messages.
activities = activities.filter(m => m.from.id === 'GeneralBots' && m.type === 'message'); activities = activities.filter(m => m.from.id === this.botId && m.type === 'message');
if (activities.length) { if (activities.length) {
// Print other messages. // Print other messages.
@ -214,5 +210,12 @@ export class WhatsappDirectLine extends GBService {
'cache-control': 'no-cache' 'cache-control': 'no-cache'
} }
}; };
try {
const result = request.post(options);
GBLog.info(result);
} catch (error) {
GBLog.error(`Error sending message to Whatsapp provider ${error}`);
}
} }
} }

View file

@ -52,10 +52,20 @@ import { GBMinService } from '../packages/core.gbapp/services/GBMinService';
const appPackages: IGBPackage[] = []; const appPackages: IGBPackage[] = [];
/**
* Global shared server data;
*/
export class RootData {
public proxyAddress: string;
}
/** /**
* General Bots open-core entry point. * General Bots open-core entry point.
*/ */
export class GBServer { export class GBServer {
public static globals: RootData;
/** /**
* Program entry-point. * Program entry-point.
*/ */
@ -66,6 +76,7 @@ export class GBServer {
// Creates a basic HTTP server that will serve several URL, one for each // Creates a basic HTTP server that will serve several URL, one for each
// bot instance. // bot instance.
GBServer.globals = new RootData();
const port = GBConfigService.getServerPort(); const port = GBConfigService.getServerPort();
const server = express(); const server = express();
server.use(bodyParser.json()); server.use(bodyParser.json());
@ -94,7 +105,7 @@ export class GBServer {
// Ensure that local development proxy is setup. // Ensure that local development proxy is setup.
GBLog.info(`Establishing a development local proxy (ngrok)...`); GBLog.info(`Establishing a development local proxy (ngrok)...`);
const proxyAddress: string = await core.ensureProxy(port); GBServer.globals.proxyAddress = await core.ensureProxy(port);
// Creates a boot instance or load it from storage. // Creates a boot instance or load it from storage.
@ -103,7 +114,7 @@ export class GBServer {
await core.initStorage(); await core.initStorage();
} catch (error) { } catch (error) {
GBLog.verbose(`Error initializing storage: ${error}`); GBLog.verbose(`Error initializing storage: ${error}`);
bootInstance = await core.createBootInstance(core, azureDeployer, proxyAddress); bootInstance = await core.createBootInstance(core, azureDeployer, GBServer.globals.proxyAddress);
await core.initStorage(); await core.initStorage();
} }
@ -116,7 +127,7 @@ export class GBServer {
await core.checkStorage(azureDeployer); await core.checkStorage(azureDeployer);
await deployer.deployPackages(core, server, appPackages); await deployer.deployPackages(core, server, appPackages);
// Loads all bot instances. // Loads boot bot and other instances.
GBLog.info(`Publishing instances...`); GBLog.info(`Publishing instances...`);
const packageInstance = await importer.importIfNotExistsBotPackage( const packageInstance = await importer.importIfNotExistsBotPackage(
@ -130,7 +141,8 @@ export class GBServer {
// tslint:disable-next-line:prefer-object-spread // tslint:disable-next-line:prefer-object-spread
const fullInstance = Object.assign(packageInstance, bootInstance); const fullInstance = Object.assign(packageInstance, bootInstance);
await core.saveInstance(fullInstance); await core.saveInstance(fullInstance);
let instances: IGBInstance[] = await core.loadAllInstances(core, azureDeployer, proxyAddress); let instances: IGBInstance[] = await core.loadAllInstances(core, azureDeployer,
GBServer.globals.proxyAddress);
instances = await core.ensureInstances(instances, bootInstance, core); instances = await core.ensureInstances(instances, bootInstance, core);
if (bootInstance !== undefined) { if (bootInstance !== undefined) {
bootInstance = instances[0]; bootInstance = instances[0];
@ -139,7 +151,8 @@ export class GBServer {
// Builds minimal service infrastructure. // 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, GBServer.globals.proxyAddress);
// Deployment of local applications for the first time. // Deployment of local applications for the first time.

View file

@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"allowJs": false, "allowJs": false,
"downlevelIteration": true,
"baseUrl": "./", "baseUrl": "./",
"declaration": false, "declaration": false,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
@ -12,13 +13,21 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"outDir": "./dist", "outDir": "./dist",
"paths": { "paths": {
"*": ["types/*"], "*": [
"botlib/*": ["node_modules/botlib/*"], "types/*"
"pragmatismo-io-framework/*": ["node_modules/pragmatismo-io-framework/*"] ],
"botlib/*": [
"node_modules/botlib/*"
],
"pragmatismo-io-framework/*": [
"node_modules/pragmatismo-io-framework/*"
]
}, },
"sourceMap": true, "sourceMap": true,
"target": "es6", "target": "ESNext",
"typeRoots": ["node_modules/@types"] "typeRoots": [
"node_modules/@types"
]
}, },
"include": [ "include": [
"test/**/*", "test/**/*",
@ -26,5 +35,8 @@
"packages/*.gbapp/**/*", "packages/*.gbapp/**/*",
"packages/*.gblib/**/*" "packages/*.gblib/**/*"
], ],
"exclude": ["dist", "node_modules"] "exclude": [
"dist",
"node_modules"
]
} }