New tasks on Azure Deployer and start of Bot Farm deployer.

This commit is contained in:
Rodrigo Rodriguez (pragmatismo.io) 2018-10-14 19:58:54 -03:00
parent 7991dced80
commit 7ef4e22764
12 changed files with 717 additions and 423 deletions

View file

@ -33,21 +33,24 @@
"use strict"; "use strict";
const UrlJoin = require("url-join"); const UrlJoin = require("url-join");
import { AzureSearch } from "pragmatismo-io-framework";
import { GBMinInstance } from "botlib"; import { GBMinInstance } from "botlib";
import { IGBDialog } from "botlib"; import { IGBDialog } from "botlib";
import { GBDeployer } from "../../core.gbapp/services/GBDeployer"; import { GBDeployer } from "../../core.gbapp/services/GBDeployer";
import { GBImporter } from "../../core.gbapp/services/GBImporter"; import { GBImporter } from "../../core.gbapp/services/GBImporter";
import { GBConfigService } from "../../core.gbapp/services/GBConfigService"; import { GBConfigService } from "../../core.gbapp/services/GBConfigService";
import { KBService } from "./../../kb.gbapp/services/KBService";
import { BotAdapter } from "botbuilder"; import { BotAdapter } from "botbuilder";
import { GBAdminService } from "../services/GBAdminService"; import { GBAdminService } from "../services/GBAdminService";
import { Messages } from "../strings"; import { Messages } from "../strings";
/** /**
* Dialogs for administration tasks. * Dialogs for administration tasks.
*/ */
export class AdminDialog extends IGBDialog { export class AdminDialog extends IGBDialog {
static async createFarmCommand(text: any, min: GBMinInstance) {
}
static async undeployPackageCommand(text: any, min: GBMinInstance) { static async undeployPackageCommand(text: any, min: GBMinInstance) {
let packageName = text.split(" ")[1]; let packageName = text.split(" ")[1];
let importer = new GBImporter(min.core); let importer = new GBImporter(min.core);
@ -106,6 +109,9 @@ export class AdminDialog extends IGBDialog {
if (text === "quit") { if (text === "quit") {
await dc.replace("/"); await dc.replace("/");
} else if (cmdName === "createFarm") {
await AdminDialog.createFarmCommand(text, deployer);
await dc.replace("/admin", { firstRun: false });
} else if (cmdName === "deployPackage") { } else if (cmdName === "deployPackage") {
await AdminDialog.deployPackageCommand(text, deployer); await AdminDialog.deployPackageCommand(text, deployer);
await dc.replace("/admin", { firstRun: false }); await dc.replace("/admin", { firstRun: false });

View file

@ -0,0 +1,65 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| 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. |
| |
\*****************************************************************************/
"use strict";
import { GBMinInstance } from "botlib";
import { IGBDialog } from "botlib";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
export class BotFarmDialog extends IGBDialog {
/**
* Setup dialogs flows and define services call.
*
* @param bot The bot adapter.
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
min.dialogs.add("/createBotFarm", [
async dc => {
let locale = dc.context.activity.locale;
await dc.prompt("choicePrompt", Messages[locale].what_about_me, [
"1",
"2",
"3",
"4",
"5"
]);
},
async (dc, value) => {
let locale = dc.context.activity.locale;
await dc.context.sendActivity(Messages[locale].thanks);
}
]);
}
}

View file

@ -33,12 +33,8 @@
"use strict" "use strict"
const UrlJoin = require("url-join") const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib" import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from "sequelize-typescript" import { Sequelize } from "sequelize-typescript"
import { AzureDeployerService } from "./services/AzureDeployerService"
export class GBWhatsappPackage implements IGBPackage { export class GBWhatsappPackage implements IGBPackage {

View file

@ -0,0 +1,457 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| 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. |
| |
\*****************************************************************************/
"use strict";
import { GBService, IGBInstance } from "botlib";
const msRestAzure = require("ms-rest-azure");
import {
ResourceManagementClient,
SubscriptionClient
} from "azure-arm-resource";
import { WebSiteManagementClient } from "azure-arm-website";
import { SqlManagementClient } from "azure-arm-sql";
import { CognitiveServicesManagementClient } from "azure-arm-cognitiveservices";
import { CognitiveServicesAccount } from "azure-arm-cognitiveservices/lib/models";
import { SearchManagementClient } from "azure-arm-search";
import { WebResource, ServiceClient } from "ms-rest-js";
import * as simplegit from "simple-git/promise";
import { AppServicePlan } from "azure-arm-website/lib/models";
const git = simplegit();
const logger = require("../../../src/logger");
const UrlJoin = require("url-join");
const PasswordGenerator = require("strict-password-generator").default;
export class AzureDeployerService extends GBService {
instance: IGBInstance;
resourceClient: ResourceManagementClient.ResourceManagementClient;
webSiteClient: WebSiteManagementClient;
storageClient: SqlManagementClient;
cognitiveClient: CognitiveServicesManagementClient;
searchClient: SearchManagementClient;
provider = "Microsoft.BotService";
subscriptionClient: SubscriptionClient.SubscriptionClient;
constructor(credentials, subscriptionId) {
super();
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.subscriptionClient = new SubscriptionClient.default(credentials);
}
public async getSubscriptions() {
this.subscriptionClient.subscriptions.list();
}
public async deploy(
instance: IGBInstance,
location: string
): Promise<IGBInstance> {
logger.info(`Creating Deploy...`);
await this.createDeploy(name, location);
logger.info(`Creating Server...`);
let serverFarm = await this.createHostingPlan(
name,
`${name}-server-plan`,
location
);
await this.createServer(serverFarm.id, name, `${name}-server`, location);
let administratorLogin = AzureDeployerService.getRndAdminAccount();
let administratorPassword = AzureDeployerService.getRndPassword();
logger.info(`Creating Storage...`);
let storageServerName = `${name}-storage`;
await this.createStorageServer(
name,
`${storageServerName}-server`,
administratorLogin,
administratorPassword,
storageServerName,
location
);
await this.createStorage(
name,
storageServerName,
`${name}-storage`,
location
);
instance.storageUsername = administratorLogin;
instance.storagePassword = administratorPassword;
instance.storageName = storageServerName;
instance.storageDialect = "mssql";
instance.storageServerName = storageServerName;
logger.info(`Creating Search...`);
let search = await this.createSearch(name, `${name}-search`, location);
logger.info(`Creating Bot...`);
//await this.createBot(credentials.tokenCache._entries[0].accessToken,
// name, name, name, 'global', subscriptionId, tenantId);
logger.info(`Creating NLP...`);
let nlp = await this.createNLP(name, `${name}-nlp`, location);
let keys = await this.cognitiveClient.accounts.listKeys(name, nlp.name);
instance.nlpEndpoint = nlp.endpoint;
instance.nlpKey = keys.key1;
logger.info(`Creating Speech...`);
let speech = await this.createSpeech(name, `${name}-speech`, location);
keys = await this.cognitiveClient.accounts.listKeys(name, speech.name);
instance.speechKeyEndpoint = speech.endpoint;
instance.speechKey = keys.key1;
logger.info(`Creating SpellChecker...`);
let spellChecker = await this.createSpellChecker(
name,
`${name}-spellchecker`,
location
);
keys = await this.cognitiveClient.accounts.listKeys(
name,
spellChecker.name
);
instance.spellCheckerKey = keys.key1;
instance.spellCheckerEndpoint = spellChecker.endpoint;
logger.info(`Creating Text Analytics...`);
let textAnalytics = await this.createTextAnalytics(
name,
`${name}-textanalytics`,
location
);
keys = await this.cognitiveClient.accounts.listKeys(
name,
textAnalytics.name
);
instance.textAnalyticsServerUrl = textAnalytics.endpoint;
instance.textAnalyticsKey = keys.key1;
logger.info(`Cleaning Deploy it can take a while...`);
// DISABLED: await this.dangerouslyDeleteDeploy(name);
}
private async dangerouslyDeleteDeploy(name) {
return this.resourceClient.resourceGroups.deleteMethod(name);
}
private async createStorageServer(
group,
name,
administratorLogin,
administratorPassword,
serverName,
location
) {
var 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) {
let query = `subscriptions/${subscriptionId}/providers/${
this.provider
}/register?api-version=2018-02-01`;
let requestUrl = UrlJoin(baseUrl, query);
let req = new WebResource();
req.method = "POST";
req.url = requestUrl;
req.headers = {};
req.headers["Content-Type"] = "application/json; charset=utf-8";
req.headers["accept-language"] = "*";
req.headers["x-ms-client-request-id"] = msRestAzure.generateUuid();
req.headers["Authorization"] = "Bearer " + accessToken;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
}
private async createBot(
accessToken,
botId,
group,
name,
location,
subscriptionId,
tenantId
) {
let baseUrl = `https://management.azure.com/`;
let appId = "";
let description = "";
let endpoint = "";
let nlpKey = "";
let nlpAppId = "3";
let parameters = {
parameters: {
location: location,
sku: {
name: "F0"
},
name: name,
//"type": "sampletype",
id: botId,
kind: "sdk",
properties: {
description: description,
displayName: name,
endpoint: endpoint,
iconUrl: "http://myicon",
luisAppIds: [nlpAppId],
luisKey: nlpKey,
msaAppId: appId
}
}
};
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=2017-12-01`;
let requestUrl = UrlJoin(baseUrl, query);
let req = new WebResource();
req.method = "PUT";
req.url = requestUrl;
req.headers = {};
req.headers["Content-Type"] = "application/json";
req.headers["accept-language"] = "*";
//req.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
req.headers["Authorization"] = "Bearer " + accessToken;
let requestContent = JSON.stringify(parameters);
req.body = requestContent;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
}
private async createSearch(group, name, location) {
var params = {
sku: { name: "free" },
location: location
};
return this.searchClient.services.createOrUpdate(group, name, params);
}
private async createStorage(group, serverName, name, location) {
var params = {
sku: { name: "Free" },
createMode: "Default",
location: location
};
return this.storageClient.databases.createOrUpdate(
group,
serverName,
name,
params
);
}
private async createCognitiveServices(
group,
name,
location,
kind
): Promise<CognitiveServicesAccount> {
// * 'Bing.Autosuggest.v7', 'Bing.CustomSearch',
// * 'Bing.Search.v7', 'Bing.Speech', 'Bing.SpellCheck.v7', 'ComputerVision',
// * 'ContentModerator', 'CustomSpeech', 'CustomVision.Prediction',
// * 'CustomVision.Training', 'Emotion', 'Face', 'LUIS', 'QnAMaker',
// * 'SpeakerRecognition', 'SpeechTranslation', 'TextAnalytics',
// * 'TextTranslation', 'WebLM'
let params = {
sku: { name: "F0" },
createMode: "Default",
location: location,
kind: kind,
properties: {}
};
return await this.cognitiveClient.accounts.create(group, name, params);
}
private async createSpeech(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
location,
"SpeechServices"
);
}
private async createNLP(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, location, "LUIS");
}
private async createSpellChecker(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
"global",
"Bing.SpellCheck.v7"
);
}
private async createTextAnalytics(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
location,
"TextAnalytics"
);
}
private async createDeploy(name, location) {
var params = { location: location };
return this.resourceClient.resourceGroups.createOrUpdate(name, params);
}
private async createHostingPlan(
group,
name,
location
): Promise<AppServicePlan> {
let params = {
serverFarmWithRichSkuName: name,
location: location,
sku: {
name: "F1",
capacity: 1,
tier: "Free"
}
};
return this.webSiteClient.appServicePlans.createOrUpdate(
group,
name,
params
);
}
private async createServer(farmId, group, name, location) {
var parameters = {
location: location,
serverFarmId: farmId
};
return this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
}
private async updateWebisteConfig(group, serverFarmId, name, location) {
var siteConfig = {
location: location,
serverFarmId: serverFarmId,
numberOfWorkers: 1,
phpVersion: "5.5"
};
return this.webSiteClient.webApps.createOrUpdateConfiguration(
group,
name,
siteConfig
);
}
private deleteDeploy(name) {
return this.resourceClient.resourceGroups.deleteMethod(name);
}
async deployGeneralBotsToAzure() {
let status = await git.status();
}
private static getRndAdminAccount() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: true,
lowerCaseAlpha: true,
number: true,
specialCharacter: true,
minimumLength: 8,
maximumLength: 8
};
let password = passwordGenerator.generatePassword(options);
return `sa${password}`;
}
private static getRndPassword() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: true,
lowerCaseAlpha: true,
number: true,
specialCharacter: true,
minimumLength: 8,
maximumLength: 8
};
let password = passwordGenerator.generatePassword(options);
return password;
}
}

View file

@ -0,0 +1,22 @@
export const Messages = {
"en-US": {
about_suggestions: "Suggestions are welcomed and improve my quality...",
what_about_service: "What about my service?",
glad_you_liked: "I'm glad you liked. I'm here for you.",
we_will_improve: "Let's take note of that, thanks for sharing.",
what_about_me: "What about the service, please rate between 1 and 5.",
thanks: "Thanks!",
im_sorry_lets_try: "I'm sorry. Let's try again...",
great_thanks: "Great, thanks for sharing your thoughts."
},
"pt-BR": {
about_suggestions: "Sugestões melhoram muito minha qualidade...",
what_about_service:"O que achou do meu atendimento?",
glad_you_liked: "Bom saber que você gostou. Conte comigo.",
we_will_improve: "Vamos registrar sua questão, obrigado pela sinceridade.",
what_about_me: "O que achou do meu atendimento, de 1 a 5?",
thanks: "Obrigado!",
im_sorry_lets_try: "Desculpe-me, vamos tentar novamente.",
great_thanks: "Ótimo, obrigado por contribuir com sua resposta."
}
};

View file

@ -1,304 +0,0 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| 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. |
| |
\*****************************************************************************/
'use strict';
import { GBService, IGBInstance } from "botlib"
const msRestAzure = require('ms-rest-azure');
import { ResourceManagementClient } from 'azure-arm-resource'
import { WebSiteManagementClient } from 'azure-arm-website';
import { SqlManagementClient } from "azure-arm-sql";
import { CognitiveServicesManagementClient } from "azure-arm-cognitiveservices";
import { CognitiveServicesAccount } from "azure-arm-cognitiveservices/lib/models";
import { SearchManagementClient } from "azure-arm-search";
import { BotConfiguration, BotService, EndpointService, IBotService, IConnectedService, ServiceTypes } from 'botframework-config';
import { WebResource, ServiceClient } from "ms-rest-js";
import * as simplegit from 'simple-git/promise';
import { AppServicePlan } from "azure-arm-website/lib/models";
const git = simplegit();
const logger = require("../../../src/logger");
const UrlJoin = require("url-join")
export class AzureDeployerService extends GBService {
instance: IGBInstance
resourceClient: ResourceManagementClient.ResourceManagementClient;
webSiteClient: WebSiteManagementClient;
storageClient: SqlManagementClient;
cognitiveClient: CognitiveServicesManagementClient;
searchClient: SearchManagementClient;
provider = 'Microsoft.BotService';
public async process(username: any, password: any, instance: IGBInstance,
subscriptionId: string, location: string) {
let _this = this;
msRestAzure.loginWithUsernamePassword(username, password, async (err, credentials) => {
_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);
let name = "generalbots";
let administratorLogin = ""
let administratorPassword = ""
let serverName = name + "";
let tenantId = '';
logger.info(`Creating Deploy...`);
let deploymentName = await this.createDeploy(name, location);
logger.info(`Creating Server...`);
let serverFarm = await this.createHostingPlan(name, `${name}-server-plan`, location);
await this.createServer(serverFarm.id, name, `${name}-server`, location);
logger.info(`Creating Storage...`);
//await this.createStorageServer(name, `${name}-storage-server`, administratorLogin, administratorPassword, serverName, location);
//await this.createStorage(name, name, `${name}-storage`, location);
logger.info(`Creating NLP...`);
//await this.createNLP(name, `${name}-nlp`, location);
logger.info(`Creating Speech...`);
//await this.createSpeech(name, `${name}-speech`, location);
logger.info(`Creating SpellChecker...`);
//await this.createSpellChecker(name, `${name}-spellchecker`, location);
logger.info(`Creating Text Analytics...`);
//await this.createTextAnalytics(name, `${name}-textanalytics`, location);
logger.info(`Creating Search...`);
//await this.createSearch(name, `${name}-search`, location);
logger.info(`Creating Bot...`);
//await this.createBot(credentials.tokenCache._entries[0].accessToken,
// name, name, name, 'global', subscriptionId, tenantId);
logger.info(`Cleaning Deploy it can take a while...`);
// DISABLED: await this.dangerouslyDeleteDeploy(name);
});
}
private async dangerouslyDeleteDeploy(name) {
return this.resourceClient.resourceGroups.deleteMethod(name);
}
private async createStorageServer(group, name, administratorLogin,
administratorPassword, serverName, location) {
var 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, ){
let query = `subscriptions/${subscriptionId}/providers/${this.provider}/register?api-version=2018-02-01`
let requestUrl = UrlJoin(baseUrl, query);
let req = new WebResource();
req.method = 'POST';
req.url = requestUrl;
req.headers = {};
req.headers['Content-Type'] = 'application/json; charset=utf-8';
req.headers["accept-language"] = '*'
req.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
req.headers['Authorization'] = 'Bearer ' + accessToken;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
}
private async createBot(accessToken, botId, group, name, location, subscriptionId, tenantId) {
let baseUrl = `https://management.azure.com/`;
let appId = '2cac4573-0aea-442a-a222-dcc340000000';
let description = 'description';
let endpoint = 'http://localhost:4242/';
let nlpKey = 'c5869c6c13854434a3f228aad2d6dfb6';
let nlpAppId = "3e431b4f-96a4-4bdb-b2d5-3ea462ddb773";
let parameters = { parameters:{
"location": location,
"sku": {
"name": "F0"
},
"name": name,
//"type": "sampletype",
"id": botId,
"kind": "sdk",
"properties": {
"description": description,
"displayName": name,
"endpoint": endpoint,
"iconUrl": "http://myicon",
"luisAppIds": [
nlpAppId,
],
"luisKey": nlpKey,
"msaAppId": appId
}
}}
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${this.provider}/botServices/${botId}?api-version=2017-12-01`;
let requestUrl = UrlJoin(baseUrl, query);
let req = new WebResource();
req.method = 'PUT';
req.url = requestUrl;
req.headers = {};
req.headers['Content-Type'] = 'application/json';
req.headers["accept-language"] = '*'
//req.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
req.headers['Authorization'] = 'Bearer ' + accessToken;
let requestContent = JSON.stringify(parameters);
req.body = requestContent;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
}
private async createSearch(group, name, location) {
var params = {
sku: { name: 'free' },
location: location
};
return this.searchClient.services.createOrUpdate(group, name, params);
}
private async createStorage(group, serverName, name, location) {
var params = {
sku: { name: 'Free' },
createMode: 'Default',
location: location
};
return this.storageClient.databases.createOrUpdate(group,
serverName, name, params);
}
private async createCognitiveServices(group, name, location, kind): Promise<CognitiveServicesAccount> {
// * 'Bing.Autosuggest.v7', 'Bing.CustomSearch',
// * 'Bing.Search.v7', 'Bing.Speech', 'Bing.SpellCheck.v7', 'ComputerVision',
// * 'ContentModerator', 'CustomSpeech', 'CustomVision.Prediction',
// * 'CustomVision.Training', 'Emotion', 'Face', 'LUIS', 'QnAMaker',
// * 'SpeakerRecognition', 'SpeechTranslation', 'TextAnalytics',
// * 'TextTranslation', 'WebLM'
let params = {
sku: { name: 'F0' },
createMode: 'Default',
location: location,
kind: kind,
properties: {}
};
return await this.cognitiveClient.accounts.create(group, name, params);
}
private async createSpeech(group, name, location): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, location, 'SpeechServices');
}
private async createNLP(group, name, location): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, location, 'LUIS');
}
private async createSpellChecker(group, name, location): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, 'global', 'Bing.SpellCheck.v7');
}
private async createTextAnalytics(group, name, location): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, location, 'TextAnalytics');
}
private async createDeploy(name, location) {
var params = { location: location };
return this.resourceClient.resourceGroups.createOrUpdate(name, params);
}
private async createHostingPlan(group, name, location):Promise<AppServicePlan> {
let params = {
serverFarmWithRichSkuName: name,
location: location,
sku: {
name: 'F1',
capacity: 1,
tier: 'Free'
}
};
return this.webSiteClient.appServicePlans.createOrUpdate(group, name, params);
}
private async createServer(farmId, group, name, location) {
var parameters = {
location: location,
serverFarmId: farmId
};
return this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
}
private async updateWebisteConfig(group, serverFarmId, name, location) {
var siteConfig = {
location: location,
serverFarmId: serverFarmId,
numberOfWorkers: 1,
phpVersion: '5.5'
};
return this.webSiteClient.webApps.createOrUpdateConfiguration(group, name, siteConfig);
}
private deleteDeploy(name) {
return this.resourceClient.resourceGroups.deleteMethod(name);
}
async deployGeneralBotsToAzure(){
let status = await git.status();
}
}

View file

@ -65,9 +65,9 @@ export class GuaribasInstance extends Model<GuaribasInstance>
@AutoIncrement @AutoIncrement
@Column @Column
instanceId: number; instanceId: number;
@Column @Column
botServerUrl:string; botServerUrl: string;
@Column @Column
whoAmIVideo: string; whoAmIVideo: string;
@ -109,10 +109,10 @@ export class GuaribasInstance extends Model<GuaribasInstance>
@Column @Column
authenticatorTenant: string; authenticatorTenant: string;
@Column @Column
authenticatorAuthorityHostUrl: string; authenticatorAuthorityHostUrl: string;
@Column @Column
authenticatorClientId: string; authenticatorClientId: string;
@ -148,13 +148,19 @@ export class GuaribasInstance extends Model<GuaribasInstance>
@Column @Column
smsServiceNumber: string; smsServiceNumber: string;
@Column @Column
speechKey: string; speechKey: string;
@Column
speechKeyEndpoint: string;
@Column @Column
spellcheckerKey: string; spellcheckerKey: string;
@Column
spellcheckerEndpoint: string;
@Column @Column
theme: string; theme: string;
@ -168,11 +174,11 @@ export class GuaribasInstance extends Model<GuaribasInstance>
nlpAppId: string; nlpAppId: string;
@Column @Column
nlpSubscriptionKey: string; nlpKey: string;
@Column @Column
@Column({ type: DataType.STRING(512) }) @Column({ type: DataType.STRING(512) })
nlpServerUrl: string; nlpEndpoint: string;
@Column @Column
searchHost: string; searchHost: string;
@ -186,6 +192,24 @@ export class GuaribasInstance extends Model<GuaribasInstance>
@Column @Column
searchIndexer: string; searchIndexer: string;
@Column
storageUsername: string;
@Column
storagePassword: string;
@Column
storageName: string;
@Column
storageServer: string;
@Column
storageDialect: string;
@Column
storagePath: string;
/* Settings section of bot.json */ /* Settings section of bot.json */
@Column(DataType.FLOAT) @Column(DataType.FLOAT)

View file

@ -100,8 +100,8 @@ export class GBConversationalService implements IGBConversationalService {
const model = new LuisRecognizer({ const model = new LuisRecognizer({
applicationId: min.instance.nlpAppId, applicationId: min.instance.nlpAppId,
endpointKey: min.instance.nlpSubscriptionKey, endpointKey: min.instance.nlpKey,
endpoint: min.instance.nlpServerUrl endpoint: min.instance.nlpEndpoint
}); });
let nlp: any; let nlp: any;

View file

@ -30,55 +30,83 @@
| | | |
\*****************************************************************************/ \*****************************************************************************/
"use strict" "use strict";
const logger = require("../../../src/logger") const logger = require("../../../src/logger");
import { Sequelize } from "sequelize-typescript" import { Sequelize } from "sequelize-typescript";
import { GBConfigService } from "./GBConfigService" import { GBConfigService } from "./GBConfigService";
import { IGBInstance, IGBCoreService } from "botlib" import { IGBInstance, IGBCoreService } from "botlib";
import { GuaribasInstance } from "../models/GBModel" import { GuaribasInstance } from "../models/GBModel";
import { GBAdminService } from "../../admin.gbapp/services/GBAdminService"; import { GBAdminService } from "../../admin.gbapp/services/GBAdminService";
import * as fs from "fs";
import { AzureDeployerService } from "../../azuredeployer.gbapp/services/AzureDeployerService";
const msRestAzure = require("ms-rest-azure");
/** /**
* Core service layer. * Core service layer.
*/ */
export class GBCoreService implements IGBCoreService { export class GBCoreService implements IGBCoreService {
async ensureCloud() {
if (!fs.existsSync(".env")) {
return;
}
logger.warn(
"This mechanism will only work for organizational ids and ids that are not 2FA enabled."
);
let credentials = await msRestAzure.loginWithUsernamePassword(
"",
""
);
let subscriptionId = "";
let s = new AzureDeployerService(credentials, subscriptionId);
let instance = new GuaribasInstance();
await s.deploy(instance, "westus");
instance.save();
let content = `STORAGE_HOST = ${instance.storageServer}\n
STORAGE_NAME, STORAGE_USERNAME, STORAGE_PASSWORD, STORAGE_DIALECT`;
fs.writeFileSync(".env", content);
}
/** /**
* Data access layer instance. * Data access layer instance.
*/ */
public sequelize: Sequelize public sequelize: Sequelize;
/** /**
* Administrative services. * Administrative services.
*/ */
public adminService: GBAdminService public adminService: GBAdminService;
/** /**
* Allows filtering on SQL generated before send to the database. * Allows filtering on SQL generated before send to the database.
*/ */
private queryGenerator: any private queryGenerator: any;
/** /**
* Custom create table query. * Custom create table query.
*/ */
private createTableQuery: (tableName, attributes, options) => string private createTableQuery: (tableName, attributes, options) => string;
/** /**
* Custom change column query. * Custom change column query.
*/ */
private changeColumnQuery: (tableName, attributes) => string private changeColumnQuery: (tableName, attributes) => string;
/** /**
* Dialect used. Tested: mssql and sqlite. * Dialect used. Tested: mssql and sqlite.
*/ */
private dialect: string private dialect: string;
/** /**
* Constructor retrieves default values. * Constructor retrieves default values.
*/ */
constructor() { constructor() {
this.dialect = GBConfigService.get("STORAGE_DIALECT") this.dialect = GBConfigService.get("STORAGE_DIALECT");
this.adminService = new GBAdminService(this) this.adminService = new GBAdminService(this);
} }
/** /**
@ -87,29 +115,29 @@ export class GBCoreService implements IGBCoreService {
async initDatabase() { async initDatabase() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
let host: string | undefined let host: string | undefined;
let database: string | undefined let database: string | undefined;
let username: string | undefined let username: string | undefined;
let password: string | undefined let password: string | undefined;
let storage: string | undefined let storage: string | undefined;
if (this.dialect === "mssql") { if (this.dialect === "mssql") {
host = GBConfigService.get("STORAGE_HOST") host = GBConfigService.get("STORAGE_HOST");
database = GBConfigService.get("STORAGE_NAME") database = GBConfigService.get("STORAGE_NAME");
username = GBConfigService.get("STORAGE_USERNAME") username = GBConfigService.get("STORAGE_USERNAME");
password = GBConfigService.get("STORAGE_PASSWORD") password = GBConfigService.get("STORAGE_PASSWORD");
} else if (this.dialect === "sqlite") { } else if (this.dialect === "sqlite") {
storage = GBConfigService.get("STORAGE_STORAGE") storage = GBConfigService.get("STORAGE_STORAGE");
} }
let logging = let logging =
GBConfigService.get("STORAGE_LOGGING") === "true" GBConfigService.get("STORAGE_LOGGING") === "true"
? (str: string) => { ? (str: string) => {
logger.info(str) logger.info(str);
} }
: false : false;
let encrypt = GBConfigService.get("STORAGE_ENCRYPT") === "true" let encrypt = GBConfigService.get("STORAGE_ENCRYPT") === "true";
this.sequelize = new Sequelize({ this.sequelize = new Sequelize({
host: host, host: host,
@ -130,30 +158,30 @@ export class GBCoreService implements IGBCoreService {
evict: 40000, evict: 40000,
acquire: 40000 acquire: 40000
} }
}) });
if (this.dialect === "mssql") { if (this.dialect === "mssql") {
this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator;
this.createTableQuery = this.queryGenerator.createTableQuery this.createTableQuery = this.queryGenerator.createTableQuery;
this.queryGenerator.createTableQuery = ( this.queryGenerator.createTableQuery = (
tableName, tableName,
attributes, attributes,
options options
) => this.createTableQueryOverride(tableName, attributes, options) ) => this.createTableQueryOverride(tableName, attributes, options);
this.changeColumnQuery = this.queryGenerator.changeColumnQuery this.changeColumnQuery = this.queryGenerator.changeColumnQuery;
this.queryGenerator.changeColumnQuery = (tableName, attributes) => this.queryGenerator.changeColumnQuery = (tableName, attributes) =>
this.changeColumnQueryOverride(tableName, attributes) this.changeColumnQueryOverride(tableName, attributes);
} }
resolve() resolve();
} catch (error) { } catch (error) {
reject(error) reject(error);
} }
}) });
} }
/** /**
* SQL: * SQL:
* *
* // let sql: string = '' + * // let sql: string = '' +
* // 'IF OBJECT_ID(\'[UserGroup]\', \'U\') IS NULL\n' + * // 'IF OBJECT_ID(\'[UserGroup]\', \'U\') IS NULL\n' +
* // 'CREATE TABLE [UserGroup] (\n' + * // 'CREATE TABLE [UserGroup] (\n' +
@ -171,38 +199,37 @@ export class GBCoreService implements IGBCoreService {
tableName, tableName,
attributes, attributes,
options options
]) ]);
const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/ const re1 = /CREATE\s+TABLE\s+\[([^\]]*)\]/;
const matches = re1.exec(sql) const matches = re1.exec(sql);
if (matches) { if (matches) {
const table = matches[1] const table = matches[1];
const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/ const re2 = /PRIMARY\s+KEY\s+\(\[[^\]]*\](?:,\s*\[[^\]]*\])*\)/;
sql = sql.replace( sql = sql.replace(
re2, re2,
(match: string, ...args: any[]): string => { (match: string, ...args: any[]): string => {
return "CONSTRAINT [" + table + "_pk] " + match return "CONSTRAINT [" + table + "_pk] " + match;
} }
) );
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
const re4 = /\[([^\]]*)\]/g const re4 = /\[([^\]]*)\]/g;
sql = sql.replace( sql = sql.replace(
re3, re3,
(match: string, ...args: any[]): string => { (match: string, ...args: any[]): string => {
const fkcols = args[0] const fkcols = args[0];
let fkname = table let fkname = table;
let matches = re4.exec(fkcols) let matches = re4.exec(fkcols);
while (matches != null) { while (matches != null) {
fkname += "_" + matches[1] fkname += "_" + matches[1];
matches = re4.exec(fkcols) matches = re4.exec(fkcols);
} }
return "CONSTRAINT [" + fkname + "_fk] FOREIGN KEY (" + fkcols + ")" return "CONSTRAINT [" + fkname + "_fk] FOREIGN KEY (" + fkcols + ")";
} }
) );
} }
return sql return sql;
} }
/** /**
* SQL: * SQL:
* let sql = '' + * let sql = '' +
@ -215,22 +242,22 @@ export class GBCoreService implements IGBCoreService {
let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [ let sql: string = this.changeColumnQuery.apply(this.queryGenerator, [
tableName, tableName,
attributes attributes
]) ]);
const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/ const re1 = /ALTER\s+TABLE\s+\[([^\]]*)\]/;
const matches = re1.exec(sql) const matches = re1.exec(sql);
if (matches) { if (matches) {
const table = matches[1] const table = matches[1];
const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g const re2 = /(ADD\s+)?CONSTRAINT\s+\[([^\]]*)\]\s+FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
const re3 = /\[([^\]]*)\]/g const re3 = /\[([^\]]*)\]/g;
sql = sql.replace( sql = sql.replace(
re2, re2,
(match: string, ...args: any[]): string => { (match: string, ...args: any[]): string => {
const fkcols = args[2] const fkcols = args[2];
let fkname = table let fkname = table;
let matches = re3.exec(fkcols) let matches = re3.exec(fkcols);
while (matches != null) { while (matches != null) {
fkname += "_" + matches[1] fkname += "_" + matches[1];
matches = re3.exec(fkcols) matches = re3.exec(fkcols);
} }
return ( return (
(args[0] ? args[0] : "") + (args[0] ? args[0] : "") +
@ -239,25 +266,25 @@ export class GBCoreService implements IGBCoreService {
"_fk] FOREIGN KEY (" + "_fk] FOREIGN KEY (" +
fkcols + fkcols +
")" ")"
) );
} }
) );
} }
return sql return sql;
} }
async syncDatabaseStructure() { async syncDatabaseStructure() {
if (GBConfigService.get("STORAGE_SYNC") === "true") { if (GBConfigService.get("STORAGE_SYNC") === "true") {
const alter = GBConfigService.get("STORAGE_SYNC_ALTER") === "true" const alter = GBConfigService.get("STORAGE_SYNC_ALTER") === "true";
const force = GBConfigService.get("STORAGE_SYNC_FORCE") === "true" const force = GBConfigService.get("STORAGE_SYNC_FORCE") === "true";
logger.info("Syncing database...") logger.info("Syncing database...");
return this.sequelize.sync({ return this.sequelize.sync({
alter: alter, alter: alter,
force: force force: force
}); });
} else { } else {
let msg = "Database synchronization is disabled."; let msg = "Database synchronization is disabled.";
logger.info(msg) logger.info(msg);
} }
} }
@ -268,12 +295,11 @@ export class GBCoreService implements IGBCoreService {
return GuaribasInstance.findAll({}); return GuaribasInstance.findAll({});
} }
/** /**
* Loads just one Bot instance by its internal Id. * Loads just one Bot instance by its internal Id.
*/ */
async loadInstanceById(instanceId: string): Promise<IGBInstance> { async loadInstanceById(instanceId: string): Promise<IGBInstance> {
let options = { where: {instanceId: instanceId} } let options = { where: { instanceId: instanceId } };
return GuaribasInstance.findOne(options); return GuaribasInstance.findOne(options);
} }
@ -281,10 +307,10 @@ export class GBCoreService implements IGBCoreService {
* Loads just one Bot instance. * Loads just one Bot instance.
*/ */
async loadInstance(botId: string): Promise<IGBInstance> { async loadInstance(botId: string): Promise<IGBInstance> {
let options = { where: {} } let options = { where: {} };
if (botId != "[default]") { if (botId != "[default]") {
options.where = { botId: botId } options.where = { botId: botId };
} }
return GuaribasInstance.findOne(options); return GuaribasInstance.findOne(options);

View file

@ -37,7 +37,7 @@ const UrlJoin = require("url-join");
const express = require("express"); const express = require("express");
const logger = require("../../../src/logger"); const logger = require("../../../src/logger");
const request = require("request-promise-native"); const request = require("request-promise-native");
const ngrok = require('ngrok'); const ngrok = require("ngrok");
var crypto = require("crypto"); var crypto = require("crypto");
var AuthenticationContext = require("adal-node").AuthenticationContext; var AuthenticationContext = require("adal-node").AuthenticationContext;
@ -67,16 +67,18 @@ import {
import { GuaribasInstance } from "../models/GBModel"; import { GuaribasInstance } from "../models/GBModel";
import { Messages } from "../strings"; import { Messages } from "../strings";
/** Minimal service layer for a bot. */ /** Minimal service layer for a bot. */
export class GBMinService { export class GBMinService {
core: IGBCoreService; core: IGBCoreService;
conversationalService: IGBConversationalService; conversationalService: IGBConversationalService;
adminService: IGBAdminService; adminService: IGBAdminService;
deployer: GBDeployer; deployer: GBDeployer;
corePackage = "core.gbai"; corePackage = "core.gbai";
/** /**
* Static initialization of minimal instance. * Static initialization of minimal instance.
* *
@ -108,7 +110,7 @@ export class GBMinService {
async buildMin( async buildMin(
server: any, server: any,
appPackages: Array<IGBPackage>, appPackages: Array<IGBPackage>,
instances:GuaribasInstance[] instances: GuaribasInstance[]
): Promise<GBMinInstance> { ): Promise<GBMinInstance> {
// Serves default UI on root address '/'. // Serves default UI on root address '/'.
@ -117,7 +119,7 @@ export class GBMinService {
"/", "/",
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build")) express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build"))
); );
Promise.all( Promise.all(
instances.map(async instance => { instances.map(async instance => {
// Gets the authorization key for each instance from Bot Service. // Gets the authorization key for each instance from Bot Service.
@ -298,11 +300,11 @@ export class GBMinService {
); );
} }
private async ngrokRefresh(){ private async ngrokRefresh() {
const url = await ngrok.connect(9090); // https://757c1652.ngrok.io -> http://localhost:9090 const url = await ngrok.connect(9090); // https://757c1652.ngrok.io -> http://localhost:9090
// TODO: Persist to storage and refresh each 8h. // TODO: Persist to storage and refresh each 8h.
// TODO: Update all bots definition in azure. // TODO: Update all bots definition in azure.
} }
private async buildBotAdapter(instance: any) { private async buildBotAdapter(instance: any) {
let adapter = new BotFrameworkAdapter({ let adapter = new BotFrameworkAdapter({
@ -372,15 +374,12 @@ private async ngrokRefresh(){
instance: any, instance: any,
appPackages: any[] appPackages: any[]
) { ) {
return adapter.processActivity(req, res, async context => { return adapter.processActivity(req, res, async context => {
const state = conversationState.get(context); const state = conversationState.get(context);
const dc = min.dialogs.createContext(context, state); const dc = min.dialogs.createContext(context, state);
dc.context.activity.locale = "en-US"; // TODO: Make dynamic. dc.context.activity.locale = "en-US"; // TODO: Make dynamic.
try { try {
const user = min.userState.get(dc.context); const user = min.userState.get(dc.context);
if (!user.loaded) { if (!user.loaded) {
@ -472,14 +471,13 @@ private async ngrokRefresh(){
} }
} }
} catch (error) { } catch (error) {
let msg = `ERROR: ${error.message} ${ let msg = `ERROR: ${error.message} ${error.stack ? error.stack : ""}`;
error.stack ? error.stack : "" logger.error(msg);
}`;
logger.error(msg); await dc.context.sendActivity(
Messages[dc.context.activity.locale].very_sorry_about_error
await dc.context.sendActivity(Messages[dc.context.activity.locale].very_sorry_about_error) );
await dc.begin("/ask", { isReturning: true }); await dc.begin("/ask", { isReturning: true });
} }
}); });
} }
@ -506,7 +504,7 @@ private async ngrokRefresh(){
let msg = `Error calling Direct Line client, verify Bot endpoint on the cloud. Error is: ${error}.`; let msg = `Error calling Direct Line client, verify Bot endpoint on the cloud. Error is: ${error}.`;
return Promise.reject(new Error(msg)); return Promise.reject(new Error(msg));
} }
} }
/** /**
* Gets a Speech to Text / Text to Speech token from the provider. * Gets a Speech to Text / Text to Speech token from the provider.

View file

@ -71,10 +71,12 @@
"pragmatismo-io-framework": "1.0.17", "pragmatismo-io-framework": "1.0.17",
"reflect-metadata": "0.1.12", "reflect-metadata": "0.1.12",
"request-promise-native": "1.0.5", "request-promise-native": "1.0.5",
"scanf": "^1.0.2",
"sequelize": "4.39.0", "sequelize": "4.39.0",
"sequelize-typescript": "0.6.6", "sequelize-typescript": "0.6.6",
"simple-git": "^1.105.0", "simple-git": "^1.105.0",
"sqlite3": "4.0.2", "sqlite3": "4.0.2",
"strict-password-generator": "^1.1.1",
"swagger-client": "3.8.21", "swagger-client": "3.8.21",
"tedious": "2.6.4", "tedious": "2.6.4",
"ts-node": "7.0.1", "ts-node": "7.0.1",

View file

@ -33,13 +33,11 @@
"use strict"; "use strict";
const UrlJoin = require("url-join");
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");
const MicrosoftGraph = require("@microsoft/microsoft-graph-client"); const scanf = require('scanf');
import { Sequelize } from "sequelize-typescript";
import { GBConfigService } from "../deploy/core.gbapp/services/GBConfigService"; import { GBConfigService } from "../deploy/core.gbapp/services/GBConfigService";
import { GBConversationalService } from "../deploy/core.gbapp/services/GBConversationalService"; import { GBConversationalService } from "../deploy/core.gbapp/services/GBConversationalService";
import { GBMinService } from "../deploy/core.gbapp/services/GBMinService"; import { GBMinService } from "../deploy/core.gbapp/services/GBMinService";
@ -56,7 +54,8 @@ import { GBCustomerSatisfactionPackage } from "../deploy/customer-satisfaction.g
import { IGBPackage } from "botlib"; import { IGBPackage } from "botlib";
import { GBAdminService } from "../deploy/admin.gbapp/services/GBAdminService"; import { GBAdminService } from "../deploy/admin.gbapp/services/GBAdminService";
import { GuaribasInstance } from "../deploy/core.gbapp/models/GBModel"; import { GuaribasInstance } from "../deploy/core.gbapp/models/GBModel";
import { AzureDeployerService } from "../deploy/azuredeployer.gblib/services/AzureDeployerService"; import { AzureDeployerService } from "deploy/azuredeployer.gbapp/services/AzureDeployerService";
let appPackages = new Array<IGBPackage>(); let appPackages = new Array<IGBPackage>();
@ -94,7 +93,10 @@ export class GBServer {
GBConfigService.init(); GBConfigService.init();
let core = new GBCoreService(); let core = new GBCoreService();
let instance = await core.ensureCloud();
await core.initDatabase(); await core.initDatabase();
// Boot a bot package if any. // Boot a bot package if any.