fix(general): tslint being applied in all sources.

This commit is contained in:
Rodrigo Rodriguez 2019-03-08 06:37:13 -03:00
parent a5a5f23ecd
commit 5d08457bef
28 changed files with 459 additions and 592 deletions

6
package-lock.json generated
View file

@ -3166,9 +3166,9 @@
} }
}, },
"botlib": { "botlib": {
"version": "0.1.19", "version": "0.1.21",
"resolved": "https://registry.npmjs.org/botlib/-/botlib-0.1.19.tgz", "resolved": "https://registry.npmjs.org/botlib/-/botlib-0.1.21.tgz",
"integrity": "sha512-JssUqK0NVwLTvs2zcl42jpKTsB5ocse27aVnFukV+wGuAjCeZu6HZpaTue1jTCHojMXAH1TSLNQnuCOOTxpw/w==", "integrity": "sha512-AF8Sp+SF3xN/jzOCo7tnqJfGaYkeHP0mJKcfYL0iHYbUuIVsCVtNmIottd1WTzDfKhls+ZoqclSAbzzoC0LS+Q==",
"requires": { "requires": {
"async": "2.6.2", "async": "2.6.2",
"botbuilder": "4.1.7", "botbuilder": "4.1.7",

View file

@ -66,7 +66,7 @@
"botbuilder-choices": "4.0.0-preview1.2", "botbuilder-choices": "4.0.0-preview1.2",
"botbuilder-dialogs": "4.2.0", "botbuilder-dialogs": "4.2.0",
"botbuilder-prompts": "4.0.0-preview1.2", "botbuilder-prompts": "4.0.0-preview1.2",
"botlib": "0.1.19", "botlib": "^0.1.21",
"chai": "4.2.0", "chai": "4.2.0",
"child_process": "^1.0.2", "child_process": "^1.0.2",
"chokidar": "2.1.2", "chokidar": "2.1.2",

View file

@ -38,14 +38,14 @@
const UrlJoin = require('url-join'); const UrlJoin = require('url-join');
import { BotAdapter } from 'botbuilder'; import { BotAdapter } from 'botbuilder';
import { WaterfallDialog, WaterfallStep, WaterfallStepContext } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
import { GBMinInstance } from 'botlib'; import { GBMinInstance, IGBDialog } from 'botlib';
import { IGBDialog } from 'botlib';
import { GBConfigService } from '../../core.gbapp/services/GBConfigService'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer'; import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
import { GBImporter } from '../../core.gbapp/services/GBImporterService'; import { GBImporter } from '../../core.gbapp/services/GBImporterService';
import { GBAdminService } from '../services/GBAdminService'; import { GBAdminService } from '../services/GBAdminService';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
/** /**
* Dialogs for administration tasks. * Dialogs for administration tasks.
@ -79,7 +79,10 @@ export class AdminDialog extends IGBDialog {
} }
public static async rebuildIndexPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) { public static async rebuildIndexPackageCommand(min: GBMinInstance, text: string, deployer: GBDeployer) {
await deployer.rebuildIndex(min.instance); await deployer.rebuildIndex(
min.instance,
new AzureDeployerService(deployer).getKBSearchSchema(min.instance.searchIndex)
);
} }
public static async addConnectionCommand(min: GBMinInstance, text: any) { public static async addConnectionCommand(min: GBMinInstance, text: any) {
@ -136,7 +139,7 @@ export class AdminDialog extends IGBDialog {
if (text === 'quit') { if (text === 'quit') {
return await step.replaceDialog('/'); return await step.replaceDialog('/');
} else if (cmdName === 'createFarm') { } else if (cmdName === 'createFarm') {
await AdminDialog.createFarmCommand(text, deployer); await AdminDialog.createFarmCommand(text, min);
return await step.replaceDialog('/admin', { firstRun: false }); return await step.replaceDialog('/admin', { firstRun: false });
} else if (cmdName === 'deployPackage') { } else if (cmdName === 'deployPackage') {
@ -224,9 +227,9 @@ export class AdminDialog extends IGBDialog {
await min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state); await min.adminService.setValue(min.instance.instanceId, 'AntiCSRFAttackState', state);
const url = `https://login.microsoftonline.com/${min.instance.authenticatorTenant}/oauth2/authorize?client_id=${ const url = `https://login.microsoftonline.com/${
min.instance.authenticatorClientId min.instance.authenticatorTenant
}&response_type=code&redirect_uri=${UrlJoin( }/oauth2/authorize?client_id=${min.instance.authenticatorClientId}&response_type=code&redirect_uri=${UrlJoin(
min.instance.botEndpoint, min.instance.botEndpoint,
min.instance.botId, min.instance.botId,
'/token' '/token'
@ -234,10 +237,9 @@ export class AdminDialog extends IGBDialog {
await step.context.sendActivity(Messages[locale].consent(url)); await step.context.sendActivity(Messages[locale].consent(url));
return await step.replaceDialog('/ask', {isReturning: true}); return await step.replaceDialog('/ask', { isReturning: true });
} }
]) ])
); );
} }
} }

View file

@ -36,15 +36,18 @@
'use strict'; 'use strict';
import urlJoin = require('url-join');
import { GBMinInstance, IGBCoreService, IGBPackage } from 'botlib'; import { GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
import { AdminDialog } from './dialogs/AdminDialog'; import { AdminDialog } from './dialogs/AdminDialog';
import { GuaribasAdmin } from './models/AdminModel'; import { GuaribasAdmin } from './models/AdminModel';
export class GBAdminPackage implements IGBPackage { export class GBAdminPackage implements IGBPackage {
public sysPackages: IGBPackage[] = null; public sysPackages: IGBPackage[] = undefined;
public unloadPackage(core: IGBCoreService): void {}
public getDialogs(min: GBMinInstance) {}
public unloadBot(min: GBMinInstance): void {}
public onNewSession(min: GBMinInstance, step: any): void {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([GuaribasAdmin]); core.sequelize.addModels([GuaribasAdmin]);

View file

@ -37,7 +37,7 @@
'use strict'; 'use strict';
import { AuthenticationContext, TokenResponse } from 'adal-node'; import { AuthenticationContext, TokenResponse } from 'adal-node';
import { IGBCoreService } from 'botlib'; import { IGBCoreService, IGBAdminService } from 'botlib';
import { GuaribasInstance } from '../../core.gbapp/models/GBModel'; import { GuaribasInstance } from '../../core.gbapp/models/GBModel';
import { GuaribasAdmin } from '../models/AdminModel'; import { GuaribasAdmin } from '../models/AdminModel';
const UrlJoin = require('url-join'); const UrlJoin = require('url-join');
@ -47,7 +47,7 @@ const PasswordGenerator = require('strict-password-generator').default;
/** /**
* Services for server administration. * Services for server administration.
*/ */
export class GBAdminService { export class GBAdminService implements IGBAdminService {
public static GB_PROMPT: string = 'GeneralBots: '; public static GB_PROMPT: string = 'GeneralBots: ';
public static masterBotInstanceId = 0; public static masterBotInstanceId = 0;
@ -76,7 +76,7 @@ export class GBAdminService {
return credentials; return credentials;
} }
public static getRndPassword() { public static getRndPassword(): string {
const passwordGenerator = new PasswordGenerator(); const passwordGenerator = new PasswordGenerator();
const options = { const options = {
upperCaseAlpha: true, upperCaseAlpha: true,
@ -105,7 +105,7 @@ export class GBAdminService {
return name; return name;
} }
public async setValue(instanceId: number, key: string, value: string): Promise<GuaribasAdmin> { public async setValue(instanceId: number, key: string, value: string) {
const options = { where: {} }; const options = { where: {} };
options.where = { key: key }; options.where = { key: key };
let admin = await GuaribasAdmin.findOne(options); let admin = await GuaribasAdmin.findOne(options);
@ -115,8 +115,7 @@ export class GBAdminService {
} }
admin.value = value; admin.value = value;
admin.instanceId = instanceId; admin.instanceId = instanceId;
await admin.save();
return admin.save();
} }
public async updateSecurityInfo( public async updateSecurityInfo(

View file

@ -43,8 +43,8 @@ import { GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
export class GBAnalyticsPackage implements IGBPackage { export class GBAnalyticsPackage implements IGBPackage {
public sysPackages: IGBPackage[] = null; public sysPackages: IGBPackage[] = undefined;
public getDialogs(min: GBMinInstance) {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {} public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {}
public unloadPackage(core: IGBCoreService): void {} public unloadPackage(core: IGBCoreService): void {}
public loadBot(min: GBMinInstance): void {} public loadBot(min: GBMinInstance): void {}

View file

@ -40,6 +40,7 @@ import { BotAdapter } from 'botbuilder';
import { GBMinInstance } from 'botlib'; import { GBMinInstance } from 'botlib';
import { IGBDialog } from 'botlib'; import { IGBDialog } from 'botlib';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { WaterfallDialog } from 'botlib/node_modules/botbuilder-dialogs';
export class BotFarmDialog extends IGBDialog { export class BotFarmDialog extends IGBDialog {
/** /**
@ -49,21 +50,20 @@ export class BotFarmDialog extends IGBDialog {
* @param min The minimal bot instance data. * @param min The minimal bot instance data.
*/ */
public static setup(bot: BotAdapter, min: GBMinInstance) { public static setup(bot: BotAdapter, min: GBMinInstance) {
min.dialogs.add('/createBotFarm', [ min.dialogs.add(new WaterfallDialog ('/createBotFarm', [
async step => { async step => {
const locale = step.context.activity.locale; const locale = step.context.activity.locale;
await step.prompt('choicePrompt', Messages[locale].what_about_me, [ await step.prompt('choicePrompt', Messages[locale].what_about_me);
'1',
'2', return step.next();
'3',
'4',
'5'
]);
}, },
async step => { async step => {
const locale = step.context.activity.locale; const locale = step.context.activity.locale;
await step.context.sendActivity(Messages[locale].thanks); await step.context.sendActivity(Messages[locale].thanks);
return step.next();
} }
]); ]));
} }
} }

View file

@ -37,18 +37,18 @@
'use strict'; 'use strict';
import { IGBInstance } from 'botlib'; import { IGBInstance } from 'botlib';
import { IGBInstallationDeployer } from 'botlib';
import * as fs from 'fs'; import * as fs from 'fs';
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService';
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService'; import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService';
import { AzureDeployerService } from '../services/AzureDeployerService';
import { GuaribasInstance } from '../../../packages/core.gbapp/models/GBModel';
const scanf = require('scanf'); const scanf = require('scanf');
/** /**
* Handles command-line dialog for getting info for Boot Bot. * Handles command-line dialog for getting info for Boot Bot.
*/ */
export class StartDialog { export class StartDialog {
public static async createBaseInstance() {
public static async createBaseInstance(installationDeployer: IGBInstallationDeployer) {
// No .env so asks for cloud credentials to start a new farm. // No .env so asks for cloud credentials to start a new farm.
if (!fs.existsSync(`.env`)) { if (!fs.existsSync(`.env`)) {
@ -75,7 +75,7 @@ export class StartDialog {
// Connects to the cloud and retrieves subscriptions. // Connects to the cloud and retrieves subscriptions.
const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password); const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password);
const list = await AzureDeployerService.getSubscriptions(credentials); const list = await installationDeployer.getSubscriptions(credentials);
let subscriptionId: string; let subscriptionId: string;
while (subscriptionId === undefined) { while (subscriptionId === undefined) {
@ -104,9 +104,8 @@ export class StartDialog {
process.stdout.write(`${GBAdminService.GB_PROMPT}Thank you. That is enough information.\nNow building farm...`); process.stdout.write(`${GBAdminService.GB_PROMPT}Thank you. That is enough information.\nNow building farm...`);
// Prepares the first instance on bot farm. // Prepares the first instance on bot farm.
const instance: IGBInstance = {}; const instance = <IGBInstance>{};
instance.botId = botId; instance.botId = botId;
instance.cloudUsername = username; instance.cloudUsername = username;
@ -223,7 +222,7 @@ generate manually an App ID and App Secret.\n`
private static retrieveLocation() { private static retrieveLocation() {
let location = GBConfigService.get('CLOUD_LOCATION'); let location = GBConfigService.get('CLOUD_LOCATION');
if (!location) { if (!location) {
process.stdout.write("CLOUD_LOCATION (eg. 'westus'):"); process.stdout.write('CLOUD_LOCATION (eg. \'westus\'):');
location = scanf('%s'); location = scanf('%s');
} }

View file

@ -40,8 +40,8 @@ import { GBMinInstance, IGBCoreService, IGBPackage } from 'botlib';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
export class GBAzureDeployerPackage implements IGBPackage { export class GBAzureDeployerPackage implements IGBPackage {
public sysPackages: IGBPackage[] = undefined;
public sysPackages: IGBPackage[] = null; public getDialogs(min: GBMinInstance) {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {} public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {}

View file

@ -43,33 +43,29 @@ import { SearchManagementClient } from 'azure-arm-search';
import { SqlManagementClient } from 'azure-arm-sql'; import { SqlManagementClient } from 'azure-arm-sql';
import { WebSiteManagementClient } from 'azure-arm-website'; import { WebSiteManagementClient } from 'azure-arm-website';
import { AppServicePlan } from 'azure-arm-website/lib/models'; import { AppServicePlan } from 'azure-arm-website/lib/models';
import { GBService, IGBInstance } from 'botlib'; import { IGBInstance, IGBInstallationDeployer } from 'botlib';
import { HttpMethods, ServiceClient, WebResource } from 'ms-rest-js'; import { HttpMethods, ServiceClient, WebResource } from 'ms-rest-js';
import { GBDeployer } from '../../../packages/core.gbapp/services/GBDeployer';
import * as simplegit from 'simple-git/promise';
import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../../../packages/admin.gbapp/services/GBAdminService';
import { GBCorePackage } from '../../../packages/core.gbapp'; import { GBCorePackage } from '../../../packages/core.gbapp';
import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService'; import { GBConfigService } from '../../../packages/core.gbapp/services/GBConfigService';
import { GuaribasInstance } from '../../../packages/core.gbapp/models/GBModel'; import { GBDeployer } from '../../../packages/core.gbapp/services/GBDeployer';
const Spinner = require('cli-spinner').Spinner; const Spinner = require('cli-spinner').Spinner;
const scanf = require('scanf');
const git = simplegit();
const logger = require('../../../src/logger'); const logger = require('../../../src/logger');
const UrlJoin = require('url-join'); const UrlJoin = require('url-join');
const iconUrl = 'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png'; const iconUrl = 'https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png';
const publicIp = require('public-ip'); const publicIp = require('public-ip');
export class AzureDeployerService extends GBService { export class AzureDeployerService implements IGBInstallationDeployer {
public static apiVersion = '2017-12-01'; public apiVersion = '2017-12-01';
public static defaultEndPoint = 'http://localhost:4242'; public defaultEndPoint = 'http://localhost:4242';
public instance: IGBInstance; public instance: IGBInstance;
public resourceClient: ResourceManagementClient.ResourceManagementClient; public resourceClient: ResourceManagementClient.ResourceManagementClient;
public webSiteClient: WebSiteManagementClient; public webSiteClient: WebSiteManagementClient;
public storageClient: SqlManagementClient; public storageClient: SqlManagementClient;
public cognitiveClient: CognitiveServicesManagementClient; public cognitiveClient: CognitiveServicesManagementClient;
public searchClient: SearchManagementClient; public searchClient: SearchManagementClient;
public static provider = 'Microsoft.BotService'; public provider = 'Microsoft.BotService';
public subscriptionClient: SubscriptionClient.SubscriptionClient; public subscriptionClient: SubscriptionClient.SubscriptionClient;
public accessToken: string; public accessToken: string;
public location: string; public location: string;
@ -78,15 +74,16 @@ export class AzureDeployerService extends GBService {
public deployer: GBDeployer; public deployer: GBDeployer;
constructor(deployer: GBDeployer) { constructor(deployer: GBDeployer) {
super();
this.deployer = deployer; this.deployer = deployer;
} }
public static async getSubscriptions(credentials) {
public async getSubscriptions(credentials) {
const subscriptionClient = new SubscriptionClient.default(credentials); const subscriptionClient = new SubscriptionClient.default(credentials);
return subscriptionClient.subscriptions.list(); return subscriptionClient.subscriptions.list();
} }
public static getKBSearchSchema(indexName) { public getKBSearchSchema(indexName) {
return { return {
name: indexName, name: indexName,
fields: [ fields: [
@ -187,16 +184,13 @@ export class AzureDeployerService extends GBService {
}; };
} }
public static 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');
const password = GBConfigService.get('CLOUD_PASSWORD'); const password = GBConfigService.get('CLOUD_PASSWORD');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID'); const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
const accessToken = await GBAdminService.getADALTokenFromUsername( const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
username,
password
);
const httpClient = new ServiceClient(); const httpClient = new ServiceClient();
const parameters = { const parameters = {
@ -207,14 +201,9 @@ export class AzureDeployerService extends GBService {
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${ const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider this.provider
}/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`; }/botServices/${botId}?api-version=${this.apiVersion}`;
const url = UrlJoin(baseUrl, query); const url = UrlJoin(baseUrl, query);
const req = this.createRequestObject( const req = AzureDeployerService.createRequestObject(url, accessToken, 'PATCH', JSON.stringify(parameters));
url,
accessToken,
'PATCH',
JSON.stringify(parameters)
);
const res = await httpClient.sendRequest(req); const res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) { if (!(res.bodyAsJson as any).id) {
throw res.bodyAsText; throw res.bodyAsText;
@ -222,7 +211,7 @@ export class AzureDeployerService extends GBService {
logger.info(`Bot proxy updated at: ${endpoint}.`); logger.info(`Bot proxy updated at: ${endpoint}.`);
} }
public static 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');
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID'); const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
@ -239,7 +228,7 @@ export class AzureDeployerService extends GBService {
await storageClient.firewallRules.createOrUpdate(groupName, serverName, 'gb', params); await storageClient.firewallRules.createOrUpdate(groupName, serverName, 'gb', params);
} }
public static createRequestObject(url: string, accessToken: string, verb: HttpMethods, body: string) { private static createRequestObject(url: string, accessToken: string, verb: HttpMethods, body: string) {
const req = new WebResource(); const req = new WebResource();
req.method = verb; req.method = verb;
req.url = url; req.url = url;
@ -304,19 +293,19 @@ export class AzureDeployerService extends GBService {
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.rebuildIndex(instance, this.deployer);
logger.info(`Deploying Speech...`); logger.info(`Deploying Speech...`);
const speech = await this.createSpeech(name, `${name}-speech`, instance.cloudLocation); const speech = await this.createSpeech(name, `${name}-speech`, instance.cloudLocation);
keys = await this.cognitiveClient.accounts.listKeys(name, speech.name); keys = await this.cognitiveClient.accounts.listKeys(name, speech.name);
instance.speechKeyEndpoint = speech.endpoint; instance.speechEndpoint = speech.endpoint;
instance.speechKey = keys.key1; instance.speechKey = keys.key1;
logger.info(`Deploying SpellChecker...`); logger.info(`Deploying SpellChecker...`);
const spellChecker = await this.createSpellChecker(name, `${name}-spellchecker`, instance.cloudLocation); const spellChecker = await this.createSpellChecker(name, `${name}-spellchecker`);
keys = await this.cognitiveClient.accounts.listKeys(name, spellChecker.name); keys = await this.cognitiveClient.accounts.listKeys(name, spellChecker.name);
instance.spellCheckerKey = keys.key1; instance.spellcheckerKey = keys.key1;
instance.spellCheckerEndpoint = spellChecker.endpoint; instance.spellcheckerEndpoint = spellChecker.endpoint;
logger.info(`Deploying Text Analytics...`); logger.info(`Deploying Text Analytics...`);
const textAnalytics = await this.createTextAnalytics(name, `${name}-textanalytics`, instance.cloudLocation); const textAnalytics = await this.createTextAnalytics(name, `${name}-textanalytics`, instance.cloudLocation);
@ -336,7 +325,7 @@ export class AzureDeployerService extends GBService {
instance.nlpAppId = nlpAppId; instance.nlpAppId = nlpAppId;
logger.info(`Deploying Bot...`); logger.info(`Deploying Bot...`);
instance.botEndpoint = AzureDeployerService.defaultEndPoint; instance.botEndpoint = this.defaultEndPoint;
instance = await this.internalDeployBot( instance = await this.internalDeployBot(
instance, instance,
@ -349,8 +338,8 @@ export class AzureDeployerService extends GBService {
'global', 'global',
instance.nlpAppId, instance.nlpAppId,
instance.nlpKey, instance.nlpKey,
instance.appId, instance.marketplaceId,
instance.appPassword, instance.marketplacePassword,
instance.cloudSubscriptionId instance.cloudSubscriptionId
); );
@ -359,17 +348,16 @@ export class AzureDeployerService extends GBService {
} }
public async deployToCloud( public async deployToCloud(
title, title: string,
username, username: string,
password, password: string,
cloudLocation, cloudLocation: string,
authoringKey, authoringKey: string,
appId, appId: string,
appPassword, appPassword: string,
subscriptionId subscriptionId: string
) { ) {
const instance = <IGBInstance> {};
const instance: IGBInstance = {};
instance.botId = title; instance.botId = title;
instance.cloudUsername = username; instance.cloudUsername = username;
@ -397,18 +385,6 @@ export class AzureDeployerService extends GBService {
this.accessToken = credentials.tokenCache._entries[0].accessToken; this.accessToken = credentials.tokenCache._entries[0].accessToken;
} }
private async updateWebisteConfig(group, serverFarmId, name, location) {
const siteConfig = {
location: location,
serverFarmId: serverFarmId,
numberOfWorkers: 1,
phpVersion: '5.5'
};
// TODO: Copy .env to app settings.
return this.webSiteClient.webApps.createOrUpdateConfiguration(group, name, siteConfig);
}
private async createStorageServer(group, name, administratorLogin, administratorPassword, serverName, location) { private async createStorageServer(group, name, administratorLogin, administratorPassword, serverName, location) {
const params = { const params = {
@ -423,7 +399,7 @@ export class AzureDeployerService extends GBService {
private async registerProviders(subscriptionId, baseUrl, accessToken) { private async registerProviders(subscriptionId, baseUrl, accessToken) {
const query = `subscriptions/${subscriptionId}/providers/${ const query = `subscriptions/${subscriptionId}/providers/${
AzureDeployerService.provider this.provider
}/register?api-version=2018-02-01`; }/register?api-version=2018-02-01`;
const requestUrl = UrlJoin(baseUrl, query); const requestUrl = UrlJoin(baseUrl, query);
@ -436,7 +412,6 @@ export class AzureDeployerService extends GBService {
req.headers.Authorization = 'Bearer ' + accessToken; req.headers.Authorization = 'Bearer ' + accessToken;
const httpClient = new ServiceClient(); const httpClient = new ServiceClient();
const res = await httpClient.sendRequest(req);
// TODO: Check res for error. // TODO: Check res for error.
} }
@ -457,7 +432,7 @@ export class AzureDeployerService extends GBService {
appId, appId,
appPassword, appPassword,
subscriptionId subscriptionId
) { ): Promise<IGBInstance> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const baseUrl = `https://management.azure.com/`; const baseUrl = `https://management.azure.com/`;
await this.registerProviders(subscriptionId, baseUrl, accessToken); await this.registerProviders(subscriptionId, baseUrl, accessToken);
@ -489,8 +464,8 @@ export class AzureDeployerService extends GBService {
const httpClient = new ServiceClient(); const httpClient = new ServiceClient();
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${ let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
AzureDeployerService.provider this.provider
}/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`; }/botServices/${botId}?api-version=${this.apiVersion}`;
let url = UrlJoin(baseUrl, query); let url = UrlJoin(baseUrl, query);
let req = AzureDeployerService.createRequestObject(url, accessToken, 'PUT', JSON.stringify(parameters)); let req = AzureDeployerService.createRequestObject(url, accessToken, 'PUT', JSON.stringify(parameters));
const res = await httpClient.sendRequest(req); const res = await httpClient.sendRequest(req);
@ -502,7 +477,7 @@ export class AzureDeployerService extends GBService {
setTimeout(async () => { setTimeout(async () => {
try { try {
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${ query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${
AzureDeployerService.apiVersion this.apiVersion
}`; }`;
url = UrlJoin(baseUrl, query); url = UrlJoin(baseUrl, query);
req = AzureDeployerService.createRequestObject(url, accessToken, 'GET', JSON.stringify(parameters)); req = AzureDeployerService.createRequestObject(url, accessToken, 'GET', JSON.stringify(parameters));
@ -603,7 +578,7 @@ export class AzureDeployerService extends GBService {
return await this.createCognitiveServices(group, name, location, 'LUIS'); return await this.createCognitiveServices(group, name, location, 'LUIS');
} }
private async createSpellChecker(group, name, location): Promise<CognitiveServicesAccount> { private async createSpellChecker(group, name): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, 'global', 'Bing.SpellCheck.v7'); return await this.createCognitiveServices(group, name, 'global', 'Bing.SpellCheck.v7');
} }
@ -637,5 +612,4 @@ export class AzureDeployerService extends GBService {
}; };
return this.webSiteClient.webApps.createOrUpdate(group, name, parameters); return this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
} }
} }

View file

@ -44,22 +44,20 @@ import { Sequelize } from 'sequelize-typescript';
import { ConsoleDirectLine } from './services/ConsoleDirectLine'; import { ConsoleDirectLine } from './services/ConsoleDirectLine';
export class GBConsolePackage implements IGBPackage { export class GBConsolePackage implements IGBPackage {
public sysPackages: IGBPackage[] = null;
public sysPackages: IGBPackage[] = undefined;
public channel: ConsoleDirectLine; public channel: ConsoleDirectLine;
public getDialogs(min: GBMinInstance) {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {}
}
public unloadPackage(core: IGBCoreService): void { public unloadPackage(core: IGBCoreService): void {}
}
public loadBot(min: GBMinInstance): void { public loadBot(min: GBMinInstance): void {
this.channel = new ConsoleDirectLine(min.instance.webchatKey); this.channel = new ConsoleDirectLine(min.instance.webchatKey);
} }
public unloadBot(min: GBMinInstance): void { public unloadBot(min: GBMinInstance): void {}
}
public onNewSession(min: GBMinInstance, step: any): void { public onNewSession(min: GBMinInstance, step: any): void {}
}
} }

View file

@ -40,7 +40,7 @@ const UrlJoin = require('url-join');
import { GBMinInstance, IGBPackage } from 'botlib'; import { GBMinInstance, IGBPackage } from 'botlib';
import { IGBCoreService} from 'botlib'; import { IGBCoreService } from 'botlib';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
import { WelcomeDialog } from './dialogs/WelcomeDialog'; import { WelcomeDialog } from './dialogs/WelcomeDialog';
import { WhoAmIDialog } from './dialogs/WhoAmIDialog'; import { WhoAmIDialog } from './dialogs/WhoAmIDialog';
@ -48,30 +48,20 @@ import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage }
export class GBCorePackage implements IGBPackage { export class GBCorePackage implements IGBPackage {
public static CurrentEngineName = 'guaribas-1.0.0'; public static CurrentEngineName = 'guaribas-1.0.0';
public sysPackages: IGBPackage[] = null; public sysPackages: IGBPackage[] = undefined;
public getDialogs(min: GBMinInstance) {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([GuaribasInstance, GuaribasPackage, GuaribasChannel, GuaribasException]);
GuaribasInstance,
GuaribasPackage,
GuaribasChannel,
GuaribasException
]);
} }
public unloadPackage(core: IGBCoreService): void { public unloadPackage(core: IGBCoreService): void {}
}
public loadBot(min: GBMinInstance): void { public loadBot(min: GBMinInstance): void {
WelcomeDialog.setup(min.bot, min); WelcomeDialog.setup(min.bot, min);
WhoAmIDialog.setup(min.bot, min); WhoAmIDialog.setup(min.bot, min);
} }
public unloadBot(min: GBMinInstance): void { public unloadBot(min: GBMinInstance): void {}
public onNewSession(min: GBMinInstance, step: any): void {}
}
public onNewSession(min: GBMinInstance, step: any): void {
}
} }

View file

@ -54,6 +54,7 @@ import { IGBInstance } from 'botlib';
@Table @Table
export class GuaribasInstance extends Model<GuaribasInstance> export class GuaribasInstance extends Model<GuaribasInstance>
implements IGBInstance { implements IGBInstance {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column @Column
@ -152,7 +153,7 @@ export class GuaribasInstance extends Model<GuaribasInstance>
public speechKey: string; public speechKey: string;
@Column @Column
public speechKeyEndpoint: string; public speechEndpoint: string;
@Column @Column
public spellcheckerKey: string; public spellcheckerKey: string;

View file

@ -35,22 +35,27 @@
import { TurnContext } from 'botbuilder'; import { TurnContext } from 'botbuilder';
import { WaterfallStepContext } from 'botbuilder-dialogs'; import { WaterfallStepContext } from 'botbuilder-dialogs';
import { GBMinInstance } from 'botlib'; import { GBMinInstance } from 'botlib';
import * as request from 'request-promise-native';
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
import { GBDeployer } from './GBDeployer';
const UrlJoin = require('url-join');
/** /**
* BASIC system class for extra manipulation of bot behaviour. * BASIC system class for extra manipulation of bot behaviour.
*/ */
class SysClass { class SysClass {
public min: GBMinInstance; public min: GBMinInstance;
private readonly deployer: GBDeployer;
constructor(min: GBMinInstance) { constructor(min: GBMinInstance, deployer: GBDeployer) {
this.min = min; this.min = min;
this.deployer = deployer;
} }
public async wait(seconds: number) { public async wait(seconds: number) {
const timeout = ms => new Promise(resolve => setTimeout(resolve, ms)); // tslint:disable-next-line no-string-based-set-timeout
const timeout = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
await timeout(seconds * 1000); await timeout(seconds * 1000);
} }
@ -68,7 +73,7 @@ class SysClass {
appPassword, appPassword,
subscriptionId subscriptionId
) { ) {
const service = new AzureDeployerService(this.min.deployer); const service = new AzureDeployerService(this.deployer);
await service.deployToCloud( await service.deployToCloud(
botId, botId,
username, username,
@ -80,6 +85,27 @@ class SysClass {
subscriptionId subscriptionId
); );
} }
/**
* Generic function to call any REST API.
*/
public async sendEmail(to, subject, body) {
// tslint:disable-next-line:no-console
console.log(`[E-mail]: to:${to}, subject: ${subject}, body: ${body}.`);
}
/**
* Generic function to call any REST API.
*/
public async httpGet(url: string, qs) {
const options = {
uri: UrlJoin(url , qs)
};
return await request.get(options);
}
} }
/** /**
* @fileoverview General Bots server core. * @fileoverview General Bots server core.
@ -92,9 +118,9 @@ export default class DialogClass {
public step: WaterfallStepContext; public step: WaterfallStepContext;
public internalSys: SysClass; public internalSys: SysClass;
constructor(min: GBMinInstance) { constructor(min: GBMinInstance, deployer: GBDeployer) {
this.min = min; this.min = min;
this.internalSys = new SysClass(min); this.internalSys = new SysClass(min, deployer);
} }
public sys(): SysClass { public sys(): SysClass {
@ -102,7 +128,7 @@ export default class DialogClass {
} }
public async hear(cb) { public async hear(cb) {
const idCallback = Math.floor(Math.random() * 1000000000000); const idCallback = crypto.getRandomValues(new Uint32Array(16))[0];
this.min.cbMap[idCallback] = cb; this.min.cbMap[idCallback] = cb;
await this.step.beginDialog('/hear', { id: idCallback }); await this.step.beginDialog('/hear', { id: idCallback });
} }
@ -110,17 +136,4 @@ export default class DialogClass {
public async talk(text: string) { public async talk(text: string) {
return await this.context.sendActivity(text); return await this.context.sendActivity(text);
} }
/**
* Generic function to call any REST API.
*/
public sendEmail(to, subject, body) {
// tslint:disable-next-line:no-console
console.log(`[E-mail]: to:${to}, subject: ${subject}, body: ${body}.`);
}
/**
* Generic function to call any REST API.
*/
public post(url: string, data) {}
} }

View file

@ -39,7 +39,7 @@
const logger = require('../../../src/logger'); const logger = require('../../../src/logger');
import { MessageFactory } from 'botbuilder'; import { MessageFactory } from 'botbuilder';
import { LuisRecognizer } from 'botbuilder-ai'; import { LuisRecognizer } from 'botbuilder-ai';
import { GBMinInstance, IGBConversationalService } from 'botlib'; import { GBMinInstance, IGBConversationalService, IGBCoreService } from 'botlib';
import { AzureText } from 'pragmatismo-io-framework'; import { AzureText } from 'pragmatismo-io-framework';
import { Messages } from '../strings'; import { Messages } from '../strings';
import { GBCoreService } from './GBCoreService'; import { GBCoreService } from './GBCoreService';
@ -51,9 +51,10 @@ export interface LanguagePickerSettings {
} }
export class GBConversationalService implements IGBConversationalService { export class GBConversationalService implements IGBConversationalService {
public coreService: GBCoreService;
constructor(coreService: GBCoreService) { public coreService: IGBCoreService;
constructor(coreService: IGBCoreService) {
this.coreService = coreService; this.coreService = coreService;
} }
@ -93,7 +94,7 @@ export class GBConversationalService implements IGBConversationalService {
public async routeNLP(step: any, min: GBMinInstance, text: string): Promise<boolean> { public async routeNLP(step: any, min: GBMinInstance, text: string): Promise<boolean> {
// Invokes LUIS. // Invokes LUIS.
let endpoint = min.instance.nlpEndpoint.replace('/luis/v2.0', ''); const endpoint = min.instance.nlpEndpoint.replace('/luis/v2.0', '');
const model = new LuisRecognizer({ const model = new LuisRecognizer({
applicationId: min.instance.nlpAppId, applicationId: min.instance.nlpAppId,

View file

@ -36,12 +36,13 @@
'use strict'; 'use strict';
import { IGBCoreService, IGBInstance, IGBPackage } from 'botlib'; import { IGBCoreService, IGBInstallationDeployer, IGBInstance, IGBPackage } from 'botlib';
import * as fs from 'fs'; import * as fs from 'fs';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
import { GBAdminPackage } from '../../admin.gbapp/index'; import { GBAdminPackage } from '../../admin.gbapp/index';
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
import { GBAnalyticsPackage } from '../../analytics.gblib'; import { GBAnalyticsPackage } from '../../analytics.gblib';
import { StartDialog } from '../../azuredeployer.gbapp/dialogs/StartDialog';
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
import { GBCorePackage } from '../../core.gbapp'; import { GBCorePackage } from '../../core.gbapp';
import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp'; import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp';
@ -50,8 +51,6 @@ import { GBSecurityPackage } from '../../security.gblib';
import { GBWhatsappPackage } from '../../whatsapp.gblib/index'; import { GBWhatsappPackage } from '../../whatsapp.gblib/index';
import { GuaribasInstance } from '../models/GBModel'; import { GuaribasInstance } from '../models/GBModel';
import { GBConfigService } from './GBConfigService'; import { GBConfigService } from './GBConfigService';
import { StartDialog } from '../../azuredeployer.gbapp/dialogs/StartDialog';
import { WaterfallDialog } from 'botbuilder-dialogs';
const logger = require('../../../src/logger'); const logger = require('../../../src/logger');
const opn = require('opn'); const opn = require('opn');
@ -60,6 +59,7 @@ const opn = require('opn');
* Core service layer. * Core service layer.
*/ */
export class GBCoreService implements IGBCoreService { export class GBCoreService implements IGBCoreService {
/** /**
* Data access layer instance. * Data access layer instance.
*/ */
@ -162,13 +162,13 @@ export class GBCoreService implements IGBCoreService {
} }
} }
public async checkStorage(azureDeployer: AzureDeployerService) { public async checkStorage(installationDeployer: IGBInstallationDeployer) {
try { try {
await this.sequelize.authenticate(); await this.sequelize.authenticate();
} catch (error) { } catch (error) {
logger.info('Opening storage firewall on infrastructure...'); logger.info('Opening storage firewall on infrastructure...');
if (error.parent.code === 'ELOGIN') { if (error.parent.code === 'ELOGIN') {
await this.openStorageFrontier(azureDeployer); await this.openStorageFrontier(installationDeployer);
} else { } else {
throw error; throw error;
} }
@ -193,14 +193,14 @@ export class GBCoreService implements IGBCoreService {
/** /**
* Loads all items to start several listeners. * Loads all items to start several listeners.
*/ */
public async loadInstances(): Promise<IGBInstance> { public async loadInstances(): Promise<IGBInstance[]> {
return GuaribasInstance.findAll({}); return GuaribasInstance.findAll({});
} }
/** /**
* Loads just one Bot instance by its internal Id. * Loads just one Bot instance by its internal Id.
*/ */
public async loadInstanceById(instanceId: string): Promise<IGBInstance> { public async loadInstanceById(instanceId: number): Promise<IGBInstance> {
const options = { where: { instanceId: instanceId } }; const options = { where: { instanceId: instanceId } };
return GuaribasInstance.findOne(options); return GuaribasInstance.findOne(options);
@ -240,8 +240,15 @@ STORAGE_SYNC=true
public async ensureProxy(port): Promise<string> { public async ensureProxy(port): Promise<string> {
try { try {
if (fs.existsSync('node_modules/ngrok/bin/ngrok.exe')) {
const ngrok = require('ngrok'); const ngrok = require('ngrok');
return await ngrok.connect({ port: port }); return await ngrok.connect({ port: port });
} else {
logger.warn('ngrok executable not found. Check installation or node_modules folder.');
return 'localhost';
}
} catch (error) { } catch (error) {
// There are false positive from ngrok regarding to no memory, but it's just // There are false positive from ngrok regarding to no memory, but it's just
// lack of connection. // lack of connection.
@ -267,15 +274,15 @@ STORAGE_SYNC=true
* @param azureDeployer * @param azureDeployer
* @param proxyAddress * @param proxyAddress
*/ */
public async loadAllInstances(core: GBCoreService, azureDeployer: AzureDeployerService, proxyAddress: string) { public async loadAllInstances(core: IGBCoreService, installationDeployer: IGBInstallationDeployer, proxyAddress: string) {
logger.info(`Loading instances from storage...`); logger.info(`Loading instances from storage...`);
let instances: GuaribasInstance[]; let instances: IGBInstance[];
try { try {
instances = await core.loadInstances(); instances = await core.loadInstances();
const instance = instances[0]; const instance = instances[0];
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
logger.info(`Updating bot endpoint to local reverse proxy (ngrok)...`); logger.info(`Updating bot endpoint to local reverse proxy (ngrok)...`);
await AzureDeployerService.updateBotProxy( await installationDeployer.updateBotProxy(
instance.botId, instance.botId,
instance.botId, instance.botId,
`${proxyAddress}/api/messages/${instance.botId}` `${proxyAddress}/api/messages/${instance.botId}`
@ -308,9 +315,9 @@ STORAGE_SYNC=true
* @param bootInstance * @param bootInstance
* @param core * @param core
*/ */
public async ensureInstances(instances: GuaribasInstance[], bootInstance: any, core: GBCoreService) { public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) {
if (!instances) { if (!instances) {
const instance: IGBInstance = {}; const instance = new GuaribasInstance();
await instance.save(); await instance.save();
instances = await core.loadInstances(); instances = await core.loadInstances();
} }
@ -347,11 +354,12 @@ STORAGE_SYNC=true
} }
} }
public async createBootInstance(core: GBCoreService, azureDeployer: AzureDeployerService, proxyAddress: string) { public async createBootInstance(core: GBCoreService, installationDeployer: IGBInstallationDeployer, proxyAddress: string) {
logger.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`); logger.info(`Deploying cognitive infrastructure (on the cloud / on premises)...`);
try { try {
let { instance, credentials, subscriptionId } = await StartDialog.createBaseInstance(); let { instance, credentials, subscriptionId } = await StartDialog.createBaseInstance(installationDeployer);
instance = await azureDeployer.deployFarm(proxyAddress, instance, credentials, subscriptionId); instance = await installationDeployer.deployFarm(proxyAddress, instance, credentials, subscriptionId);
core.writeEnv(instance); core.writeEnv(instance);
logger.info(`File .env written, starting General Bots...`); logger.info(`File .env written, starting General Bots...`);
GBConfigService.init(); GBConfigService.init();
@ -457,9 +465,9 @@ STORAGE_SYNC=true
* *
* @param azureDeployer Infrastructure Deployer instance. * @param azureDeployer Infrastructure Deployer instance.
*/ */
private async openStorageFrontier(deployer: AzureDeployerService) { private async openStorageFrontier(installationDeployer: IGBInstallationDeployer) {
const group = GBConfigService.get('CLOUD_GROUP'); const group = GBConfigService.get('CLOUD_GROUP');
const serverName = GBConfigService.get('STORAGE_SERVER').split('.database.windows.net')[0]; const serverName = GBConfigService.get('STORAGE_SERVER').split('.database.windows.net')[0];
await AzureDeployerService.openStorageFirewall(group, serverName); await installationDeployer.openStorageFirewall(group, serverName);
} }
} }

View file

@ -73,7 +73,7 @@ export class GBDeployer {
this.importer = importer; this.importer = importer;
} }
public static getConnectionStringFromInstance(instance: GuaribasInstance) { public static getConnectionStringFromInstance(instance: IGBInstance) {
return `Server=tcp:${instance.storageServer}.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;`;
@ -272,7 +272,7 @@ export class GBDeployer {
} }
} }
public async rebuildIndex(instance: GuaribasInstance) { public async rebuildIndex(instance: IGBInstance, searchSchema: any) {
const search = new AzureSearch( const search = new AzureSearch(
instance.searchKey, instance.searchKey,
instance.searchHost, instance.searchHost,
@ -302,7 +302,7 @@ export class GBDeployer {
throw err; throw err;
} }
} }
await search.createIndex(AzureDeployerService.getKBSearchSchema(instance.searchIndex), dsName); await search.createIndex(searchSchema, dsName);
} }
public async getPackageByName(instanceId: number, packageName: string): Promise<GuaribasPackage> { public async getPackageByName(instanceId: number, packageName: string): Promise<GuaribasPackage> {
@ -312,7 +312,7 @@ export class GBDeployer {
}); });
} }
public installDefaultGBUI() { public runOnce() {
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)...`); logger.info(`Preparing default.gbui (it may take some additional time for the first time)...`);
@ -323,7 +323,7 @@ export class GBDeployer {
} }
private async deployDataPackages( private async deployDataPackages(
core: GBCoreService, core: IGBCoreService,
botPackages: string[], botPackages: string[],
_this: this, _this: this,
generalPackages: string[], generalPackages: string[],

View file

@ -46,7 +46,7 @@ const AuthenticationContext = require('adal-node').AuthenticationContext;
import { AutoSaveStateMiddleware, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder'; import { AutoSaveStateMiddleware, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
import { ConfirmPrompt, WaterfallDialog } from 'botbuilder-dialogs'; import { ConfirmPrompt, WaterfallDialog } from 'botbuilder-dialogs';
import { GBMinInstance, IGBAdminService, IGBConversationalService, IGBCoreService, IGBPackage } from 'botlib'; import { GBMinInstance, IGBAdminService, IGBConversationalService, IGBCoreService, IGBPackage, IGBInstance } from 'botlib';
import { GBAnalyticsPackage } from '../../analytics.gblib'; import { GBAnalyticsPackage } from '../../analytics.gblib';
import { GBCorePackage } from '../../core.gbapp'; import { GBCorePackage } from '../../core.gbapp';
import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp'; import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp';
@ -97,12 +97,12 @@ export class GBMinService {
* */ * */
public async buildMin( public async buildMin(
bootInstance: GuaribasInstance, bootInstance: IGBInstance,
server: any, server: any,
appPackages: IGBPackage[], appPackages: IGBPackage[],
instances: GuaribasInstance[], instances: IGBInstance[],
deployer: GBDeployer deployer: GBDeployer
): Promise<GBMinInstance> { ) {
// Serves default UI on root address '/'. // Serves default UI on root address '/'.
const uiPackage = 'default.gbui'; const uiPackage = 'default.gbui';
@ -166,9 +166,9 @@ export class GBMinService {
); );
} }
private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: GuaribasInstance) { private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) {
server.get(`/${min.instance.botId}/token`, async (req, res) => { server.get(`/${min.instance.botId}/token`, async (req, res) => {
const state = await min.adminService.getValue(min.instance.instanceId, 'AntiCSRFAttackState'); const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState');
if (req.query.state !== state) { if (req.query.state !== state) {
const msg = 'WARNING: state field was not provided as anti-CSRF token'; const msg = 'WARNING: state field was not provided as anti-CSRF token';
logger.error(msg); logger.error(msg);
@ -218,7 +218,7 @@ export class GBMinService {
/** /**
* Returns the instance object to clients requesting bot info. * Returns the instance object to clients requesting bot info.
*/ */
private async sendInstanceToClient(req, bootInstance: GuaribasInstance, res: any, webchatToken: any) { private async sendInstanceToClient(req, bootInstance: IGBInstance, res: any, webchatToken: any) {
let botId = req.params.botId; let botId = req.params.botId;
if (botId === '[default]') { if (botId === '[default]') {
botId = bootInstance.botId; botId = bootInstance.botId;
@ -351,7 +351,7 @@ export class GBMinService {
if (sysPackage.name === 'GBWhatsappPackage') { if (sysPackage.name === 'GBWhatsappPackage') {
const url = '/instances/:botId/whatsapp'; const url = '/instances/:botId/whatsapp';
server.post(url, (req, res) => { server.post(url, (req, res) => {
p.channel.received(req, res); p['channel'].received(req, res);
}); });
} }
}, this); }, this);
@ -383,7 +383,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 state = await conversationState.get(context); const state = await conversationState.get(context);
const step = await min.dialogs.createContext(context, state); const step = await min.dialogs.createContext(context);
step.context.activity.locale = 'en-US'; // TODO: Make dynamic. step.context.activity.locale = 'en-US'; // TODO: Make dynamic.
try { try {
@ -481,10 +481,10 @@ export class GBMinService {
if (isVMCall) { if (isVMCall) {
let mainMethod = context.activity.text; let mainMethod = context.activity.text;
min.sandbox.context = context; min.sandBoxMap[mainMethod].context = context;
min.sandbox.step = step; min.sandBoxMap[mainMethod].step = step;
min.sandbox[mainMethod].bind(min.sandbox); min.sandBoxMap[mainMethod][mainMethod].bind(min.sandBoxMap[mainMethod]);
await min.sandbox[mainMethod](); await min.sandBoxMap[mainMethod][mainMethod]();
} else if (context.activity.text === 'admin') { } else if (context.activity.text === 'admin') {
await step.beginDialog('/admin'); await step.beginDialog('/admin');

View file

@ -33,10 +33,11 @@
'use strict'; 'use strict';
import { WaterfallDialog } from 'botbuilder-dialogs'; import { WaterfallDialog } from 'botbuilder-dialogs';
import { GBMinInstance, IGBCoreService } from 'botlib'; import { GBMinInstance, IGBCoreService, GBService } from 'botlib';
import * as fs from 'fs'; import * as fs from 'fs';
import { GBDeployer } from './GBDeployer'; import { GBDeployer } from './GBDeployer';
import { TSCompiler } from './TSCompiler'; import { TSCompiler } from './TSCompiler';
import GBAPIService from './GBAPIService';
import DialogClass from './GBAPIService'; import DialogClass from './GBAPIService';
const walkPromise = require('walk-promise'); const walkPromise = require('walk-promise');
@ -44,7 +45,7 @@ const logger = require('../../../src/logger');
const vm = require('vm'); const vm = require('vm');
const UrlJoin = require('url-join'); const UrlJoin = require('url-join');
const vb2ts = require('vbscript-to-typescript/dist/converter'); const vb2ts = require('vbscript-to-typescript/dist/converter');
var beautify = require('js-beautify').js; let beautify = require('js-beautify').js;
/** /**
* @fileoverview Virtualization services for emulation of BASIC. * @fileoverview Virtualization services for emulation of BASIC.
@ -55,7 +56,7 @@ var beautify = require('js-beautify').js;
* translation and enhance classic BASIC experience. * translation and enhance classic BASIC experience.
*/ */
export class GBVMService implements IGBCoreService { export class GBVMService extends GBService {
private readonly script = new vm.Script(); private readonly script = new vm.Script();
public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) { public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) {
@ -110,6 +111,10 @@ export class GBVMService implements IGBCoreService {
return 'let password = sys().generatePassword()'; return 'let password = sys().generatePassword()';
}); });
code = code.replace(/(get)(\s)(.*)/g, ($0, $1, $2) => {
return `sys().httpGet (${$2})`;
});
code = code.replace(/(create a bot farm using)(\s)(.*)/g, ($0, $1, $2, $3) => { code = code.replace(/(create a bot farm using)(\s)(.*)/g, ($0, $1, $2, $3) => {
return `sys().createABotFarmUsing (${$3})`; return `sys().createABotFarmUsing (${$3})`;
}); });
@ -207,14 +212,14 @@ export class GBVMService implements IGBCoreService {
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); const sandbox: DialogClass = new DialogClass(min, deployer);
const context = vm.createContext(sandbox); const context = vm.createContext(sandbox);
vm.runInContext(parsedCode, context); vm.runInContext(parsedCode, context);
min.sandbox = sandbox; min.sandBoxMap[mainName] = sandbox;
await deployer.deployScriptToStorage(min.instanceId, filename); await deployer.deployScriptToStorage(1, filename); // TODO: Per bot storage.
logger.info(`[GBVMService] Finished loading of ${filename}`); logger.info(`[GBVMService] Finished loading of ${filename}`);
} }
} }

View file

@ -45,23 +45,17 @@ import { GuaribasQuestionAlternate } from './models/index';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
export class GBCustomerSatisfactionPackage implements IGBPackage { export class GBCustomerSatisfactionPackage implements IGBPackage {
public sysPackages: IGBPackage[] = null; public sysPackages: IGBPackage[] = undefined;
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public getDialogs(min: GBMinInstance) {}
core.sequelize.addModels([
GuaribasQuestionAlternate
]);
}
public unloadPackage(core: IGBCoreService): void {
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([GuaribasQuestionAlternate]);
} }
public unloadPackage(core: IGBCoreService): void {}
public loadBot(min: GBMinInstance): void { public loadBot(min: GBMinInstance): void {
FeedbackDialog.setup(min.bot, min); FeedbackDialog.setup(min.bot, min);
QualityDialog.setup(min.bot, min); QualityDialog.setup(min.bot, min);
} }
public unloadBot(min: GBMinInstance): void { public unloadBot(min: GBMinInstance): void {}
public onNewSession(min: GBMinInstance, step: any): void {}
}
public onNewSession(min: GBMinInstance, step: any): void {
}
} }

View file

@ -48,31 +48,18 @@ import { FaqDialog } from './dialogs/FaqDialog';
import { MenuDialog } from './dialogs/MenuDialog'; import { MenuDialog } from './dialogs/MenuDialog';
export class GBKBPackage implements IGBPackage { export class GBKBPackage implements IGBPackage {
public sysPackages: IGBPackage[] = undefined;
public sysPackages: IGBPackage[] = null; public getDialogs(min: GBMinInstance) {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([GuaribasAnswer, GuaribasQuestion, GuaribasSubject]);
GuaribasAnswer,
GuaribasQuestion,
GuaribasSubject
]);
}
public unloadPackage(core: IGBCoreService): void {
} }
public unloadPackage(core: IGBCoreService): void {}
public loadBot(min: GBMinInstance): void { public loadBot(min: GBMinInstance): void {
AskDialog.setup(min.bot, min); AskDialog.setup(min.bot, min);
FaqDialog.setup(min.bot, min); FaqDialog.setup(min.bot, min);
MenuDialog.setup(min.bot, min); MenuDialog.setup(min.bot, min);
}
public unloadBot(min: GBMinInstance): void {
}
public onNewSession(min: GBMinInstance, step: any): void {
} }
public unloadBot(min: GBMinInstance): void {}
public onNewSession(min: GBMinInstance, step: any): void {}
} }

View file

@ -53,6 +53,7 @@ import { GuaribasPackage } from '../../core.gbapp/models/GBModel';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer'; import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models'; import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models';
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'; import { GBConfigService } from './../../core.gbapp/services/GBConfigService';
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
export class KBServiceSearchResults { export class KBServiceSearchResults {
public answer: GuaribasAnswer; public answer: GuaribasAnswer;
@ -326,7 +327,7 @@ export class KBService {
}); });
if (lastAnswer && lastQuestionId) { if (lastAnswer && lastQuestionId) {
await lastAnswer.updateAttributes({ nextId: lastQuestionId }); await lastAnswer.update({ nextId: lastQuestionId });
} }
lastAnswer = answer1; lastAnswer = answer1;
lastQuestionId = question1.questionId; lastQuestionId = question1.questionId;
@ -449,7 +450,7 @@ export class KBService {
where: { instanceId: instance.instanceId, packageId: packageId } where: { instanceId: instance.instanceId, packageId: packageId }
}); });
await deployer.rebuildIndex(instance); await deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex));
} }
/** /**
@ -468,7 +469,7 @@ export class KBService {
const p = await deployer.deployPackageToStorage(instance.instanceId, packageName); const p = await deployer.deployPackageToStorage(instance.instanceId, packageName);
await this.importKbPackage(localPath, p, instance); await this.importKbPackage(localPath, p, instance);
deployer.rebuildIndex(instance); deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex));
logger.info(`[GBDeployer] Finished import of ${localPath}`); logger.info(`[GBDeployer] Finished import of ${localPath}`);
} }
} }

View file

@ -44,29 +44,17 @@ import { Sequelize } from 'sequelize-typescript';
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models'; import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from './models';
export class GBSecurityPackage implements IGBPackage { export class GBSecurityPackage implements IGBPackage {
public sysPackages: IGBPackage[] = null; public sysPackages: IGBPackage[] = undefined;
public getDialogs(min: GBMinInstance) {}
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([ core.sequelize.addModels([GuaribasGroup, GuaribasUser, GuaribasUserGroup]);
GuaribasGroup,
GuaribasUser,
GuaribasUserGroup
]);
core;
} }
public unloadPackage(core: IGBCoreService): void { public unloadPackage(core: IGBCoreService): void {}
} public loadBot(min: GBMinInstance): void {}
public loadBot(min: GBMinInstance): void { public unloadBot(min: GBMinInstance): void {}
public onNewSession(min: GBMinInstance, step: any): void {}
}
public unloadBot(min: GBMinInstance): void {
}
public onNewSession(min: GBMinInstance, step: any): void {
}
} }

View file

@ -1,52 +1,12 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
const Path = require('path');
const Fs = require('fs'); const Fs = require('fs');
const _ = require('lodash');
const Parse = require('csv-parse');
const Async = require('async');
const UrlJoin = require('url-join'); const UrlJoin = require('url-join');
const logger = require('../../../src/logger');
import { GBService, GBServiceCallback, IGBInstance } from 'botlib'; import { GBService, IGBInstance } from 'botlib';
import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models'; import { GuaribasGroup, GuaribasUser, GuaribasUserGroup } from '../models';
export class SecService extends GBService { export class SecService extends GBService {
public async importSecurityFile(localPath: string, instance: IGBInstance) { public async importSecurityFile(localPath: string, instance: IGBInstance) {
const security = JSON.parse( const security = JSON.parse(Fs.readFileSync(UrlJoin(localPath, 'security.json'), 'utf8'));
Fs.readFileSync(UrlJoin(localPath, 'security.json'), 'utf8')
);
security.groups.forEach(group => { security.groups.forEach(group => {
const groupDb = GuaribasGroup.build({ const groupDb = GuaribasGroup.build({
instanceId: instance.instanceId, instanceId: instance.instanceId,
@ -78,16 +38,15 @@ export class SecService extends GBService {
channelName: string, channelName: string,
displayName: string displayName: string
): Promise<GuaribasUser> { ): Promise<GuaribasUser> {
return new Promise<GuaribasUser>( return new Promise<GuaribasUser>((resolve, reject) => {
(resolve, reject) => {
GuaribasUser.findOne({ GuaribasUser.findOne({
attributes: ['instanceId', 'internalAddress'], attributes: ['instanceId', 'internalAddress'],
where: { where: {
instanceId: instanceId, instanceId: instanceId,
userSystemId: userSystemId userSystemId: userSystemId
} }
}).then(user => { })
.then(user => {
if (!user) { if (!user) {
user = GuaribasUser.build(); user = GuaribasUser.build();
} }
@ -99,7 +58,8 @@ export class SecService extends GBService {
user.defaultChannel = channelName; user.defaultChannel = channelName;
user.save(); user.save();
resolve(user); resolve(user);
}).error(reject); })
.error(reject);
}); });
} }
} }

View file

@ -44,31 +44,30 @@ import { Sequelize } from 'sequelize-typescript';
import { WhatsappDirectLine } from './services/WhatsappDirectLine'; import { WhatsappDirectLine } from './services/WhatsappDirectLine';
export class GBWhatsappPackage implements IGBPackage { export class GBWhatsappPackage implements IGBPackage {
public sysPackages: IGBPackage[] = undefined;
public getDialogs(min: GBMinInstance) {}
public sysPackages: IGBPackage[] = null;
public channel: WhatsappDirectLine; public channel: WhatsappDirectLine;
public loadPackage(core: IGBCoreService, sequelize: Sequelize): void { public loadPackage(core: IGBCoreService, sequelize: Sequelize): void {}
}
public unloadPackage(core: IGBCoreService): void { public unloadPackage(core: IGBCoreService): void {}
}
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) { if (min.instance.whatsappBotKey) {
this.channel = new WhatsappDirectLine(min.botId, min.instance.whatsappBotKey, min.instance.whatsappServiceKey, this.channel = new WhatsappDirectLine(
min.instance.whatsappServiceNumber, min.instance.whatsappServiceUrl, min.instance.whatsappServiceWebhookUrl); min.botId,
min.instance.whatsappBotKey,
min.instance.whatsappServiceKey,
min.instance.whatsappServiceNumber,
min.instance.whatsappServiceUrl,
min.instance.whatsappServiceWebhookUrl
);
} }
} }
public unloadBot(min: GBMinInstance): void { public unloadBot(min: GBMinInstance): void {}
public onNewSession(min: GBMinInstance, step: any): void {}
}
public onNewSession(min: GBMinInstance, step: any): void {
}
} }

View file

@ -1,50 +1,11 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
const Path = require('path');
const Fs = require('fs');
const _ = require('lodash');
const Parse = require('csv-parse');
const Async = require('async');
const UrlJoin = require('url-join'); const UrlJoin = require('url-join');
const logger = require('../../../src/logger'); const logger = require('../../../src/logger');
const Swagger = require('swagger-client'); const Swagger = require('swagger-client');
const rp = require('request-promise'); const rp = require('request-promise');
import { GBService } from 'botlib';
import * as request from 'request-promise-native'; import * as request from 'request-promise-native';
import { GBService, GBServiceCallback, IGBInstance } from 'botlib';
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 directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json';
@ -59,8 +20,14 @@ export class WhatsappDirectLine extends GBService {
public conversationIds = {}; public conversationIds = {};
constructor(botId, directLineSecret, whatsappServiceKey, whatsappServiceNumber, whatsappServiceUrl, whatsappServiceWebhookUrl) { constructor(
botId,
directLineSecret,
whatsappServiceKey,
whatsappServiceNumber,
whatsappServiceUrl,
whatsappServiceWebhookUrl
) {
super(); super();
this.botId = botId; this.botId = botId;
@ -71,28 +38,27 @@ export class WhatsappDirectLine extends GBService {
// TODO: Migrate to Swagger 3. // TODO: Migrate to Swagger 3.
this.directLineClient = rp(this.directLineSpecUrl) this.directLineClient = rp(this.directLineSpecUrl)
.then((spec) => { .then(spec => {
return new Swagger({ return new Swagger({
spec: JSON.parse(spec.trim()), spec: JSON.parse(spec.trim()),
usePromise: true usePromise: true
}); });
}) })
.then(async (client) => { .then(async client => {
client.clientAuthorizations.add('AuthorizationBotConnector', client.clientAuthorizations.add(
new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + 'AuthorizationBotConnector',
directLineSecret, 'header')); new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header')
);
const options = { const options = {
method: 'POST', method: 'POST',
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: `${this.whatsappServiceWebhookUrl}/instances/${this.botId}/whatsapp`,
set: true set: true
}, },
headers: headers: {
{
'cache-control': 'no-cache' 'cache-control': 'no-cache'
} }
}; };
@ -106,10 +72,9 @@ export class WhatsappDirectLine extends GBService {
return client; return client;
}) })
.catch((err) => { .catch(err => {
logger.error('Error initializing DirectLine client', err); logger.error('Error initializing DirectLine client', err);
}); });
} }
public received(req, res) { public received(req, res) {
@ -125,39 +90,31 @@ export class WhatsappDirectLine extends GBService {
const conversationId = this.conversationIds[from]; const conversationId = this.conversationIds[from];
this.directLineClient.then((client) => { this.directLineClient.then(client => {
if (this.conversationIds[from] == undefined) {
if (this.conversationIds[from] == null) {
logger.info(`GBWhatsapp: Starting new conversation on Bot.`); logger.info(`GBWhatsapp: Starting new conversation on Bot.`);
client.Conversations.Conversations_StartConversation() client.Conversations.Conversations_StartConversation()
.then((response) => { .then(response => {
return response.obj.conversationId; return response.obj.conversationId;
}) })
.then((conversationId) => { .then(conversationId => {
this.conversationIds[from] = conversationId; this.conversationIds[from] = conversationId;
this.inputMessage(client, conversationId, text, this.inputMessage(client, conversationId, text, from, fromName);
from, fromName);
this.pollMessages(client, conversationId, from, fromName); this.pollMessages(client, conversationId, from, fromName);
}) })
.catch((err) => { .catch(err => {
console.error('Error starting conversation', err); console.error('Error starting conversation', err);
}); });
} else { } else {
this.inputMessage(client, conversationId, text, this.inputMessage(client, conversationId, text, from, fromName);
from, fromName);
} }
res.end(); res.end();
}); });
} }
public inputMessage(client, conversationId, text, from, fromName) { public inputMessage(client, conversationId, text, from, fromName) {
client.Conversations.Conversations_PostActivity({
client.Conversations.Conversations_PostActivity(
{
conversationId: conversationId, conversationId: conversationId,
activity: { activity: {
textFormat: 'plain', textFormat: 'plain',
@ -169,42 +126,37 @@ export class WhatsappDirectLine extends GBService {
}, },
replyToId: from replyToId: from
} }
}).catch((err) => { }).catch(err => {
logger.error(`GBWhatsapp: Error receiving message: ${err}.`); logger.error(`GBWhatsapp: Error receiving message: ${err}.`);
}); });
} }
public pollMessages(client, conversationId, from, fromName) { public pollMessages(client, conversationId, from, fromName) {
logger.info(`GBWhatsapp: Starting polling message for conversationId: logger.info(`GBWhatsapp: Starting polling message for conversationId:
${conversationId}.`); ${conversationId}.`);
setInterval(() => { setInterval(() => {
client.Conversations.Conversations_GetActivities({ client.Conversations.Conversations_GetActivities({
conversationId: conversationId: conversationId,
conversationId, watermark: this.watermark watermark: this.watermark
}) })
.then((response) => { .then(response => {
this.watermark = response.obj.watermark; this.watermark = response.obj.watermark;
return response.obj.activities; return response.obj.activities;
}) })
.then((activities) => { .then(activities => {
this.printMessages(activities, conversationId, from, fromName); this.printMessages(activities, conversationId, from, fromName);
}); });
}, this.pollInterval); }, this.pollInterval);
} }
public printMessages(activities, conversationId, from, fromName) { public printMessages(activities, conversationId, from, fromName) {
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 === 'GeneralBots' && m.type === 'message');
if (activities.length) { if (activities.length) {
// Print other messages. // Print other messages.
activities.forEach(activity => { activities.forEach(activity => {
@ -215,7 +167,6 @@ export class WhatsappDirectLine extends GBService {
} }
public printMessage(activity, conversationId, from, fromName) { public printMessage(activity, conversationId, from, fromName) {
let output = ''; let output = '';
if (activity.text) { if (activity.text) {
@ -224,7 +175,7 @@ export class WhatsappDirectLine extends GBService {
} }
if (activity.attachments) { if (activity.attachments) {
activity.attachments.forEach((attachment) => { activity.attachments.forEach(attachment => {
switch (attachment.contentType) { switch (attachment.contentType) {
case 'application/vnd.microsoft.card.hero': case 'application/vnd.microsoft.card.hero':
output += `\n${this.renderHeroCard(attachment)}`; output += `\n${this.renderHeroCard(attachment)}`;
@ -238,29 +189,25 @@ export class WhatsappDirectLine extends GBService {
}); });
} }
this.sendToDevice(conversationId, from, fromName, output); this.sendToDevice(from, output);
} }
public renderHeroCard(attachment) { public renderHeroCard(attachment) {
return `${attachment.content.title} - ${attachment.content.text}`; return `${attachment.content.title} - ${attachment.content.text}`;
} }
public async sendToDevice(conversationId, to, toName, msg) { public async sendToDevice(to, msg) {
const options = { const options = {
method: 'POST', method: 'POST',
url: UrlJoin(this.whatsappServiceUrl, 'message'), url: UrlJoin(this.whatsappServiceUrl, 'message'),
qs: qs: {
{
token: this.whatsappServiceKey, token: this.whatsappServiceKey,
phone: to, phone: to,
body: msg body: msg
}, },
headers: headers: {
{
'cache-control': 'no-cache' 'cache-control': 'no-cache'
} }
}; };
const result = await request.get(options);
} }
} }

View file

@ -40,7 +40,7 @@
const logger = require('./logger'); const logger = require('./logger');
const express = require('express'); const express = require('express');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
import { IGBInstance, IGBPackage } from 'botlib'; import { IGBInstance, IGBPackage, IGBCoreService } from 'botlib';
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService'; import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService';
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService'; import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService';
import { GuaribasInstance } from '../packages/core.gbapp/models/GBModel'; import { GuaribasInstance } from '../packages/core.gbapp/models/GBModel';
@ -50,8 +50,6 @@ import { GBCoreService } from '../packages/core.gbapp/services/GBCoreService';
import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer'; 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';
import { GBVMService } from '../packages/core.gbapp/services/GBVMService';
import { load } from 'dotenv';
const appPackages = new Array<IGBPackage>(); const appPackages = new Array<IGBPackage>();
@ -90,7 +88,7 @@ export class GBServer {
// Reads basic configuration, initialize minimal services. // Reads basic configuration, initialize minimal services.
GBConfigService.init(); GBConfigService.init();
const core = 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);
@ -103,7 +101,7 @@ export class GBServer {
logger.info(`Establishing a development local proxy (ngrok)...`); logger.info(`Establishing a development local proxy (ngrok)...`);
const proxyAddress: string = await core.ensureProxy(port); const proxyAddress: string = await core.ensureProxy(port);
// Creates a boot instance or load it frmo storage. // Creates a boot instance or load it from storage.
let bootInstance: IGBInstance = null; let bootInstance: IGBInstance = null;
try { try {
@ -130,9 +128,9 @@ export class GBServer {
'boot.gbot', 'boot.gbot',
'packages/boot.gbot' 'packages/boot.gbot'
); );
const fullInstance = Object.assign(packageInstance, bootInstance); const fullInstance = { ...packageInstance, ...bootInstance };
await core.saveInstance(fullInstance); await core.saveInstance(fullInstance);
let instances: GuaribasInstance[] = await core.loadAllInstances(core, azureDeployer, proxyAddress); let instances: IGBInstance[] = 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];
@ -145,14 +143,13 @@ export class GBServer {
// Deployment of local applications for the first time. // Deployment of local applications for the first time.
deployer.installDefaultGBUI(); deployer.runOnce();
logger.info(`The Bot Server is in RUNNING mode...`); logger.info(`The Bot Server is in RUNNING mode...`);
// Opens Navigator. // Opens Navigator.
core.openBrowserInDevelopment(); core.openBrowserInDevelopment();
} 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);

View file

@ -12,6 +12,7 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"outDir": "./dist", "outDir": "./dist",
"paths": { "paths": {
"*": ["types/*"],
"botlib/*": ["node_modules/botlib/*"], "botlib/*": ["node_modules/botlib/*"],
"pragmatismo-io-framework/*": ["node_modules/pragmatismo-io-framework/*"] "pragmatismo-io-framework/*": ["node_modules/pragmatismo-io-framework/*"]
}, },