Added Azure AD administration routines.
This commit is contained in:
parent
e7a7fcedbf
commit
c03228dbbe
18 changed files with 617 additions and 374 deletions
|
@ -30,33 +30,33 @@
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
"use strict"
|
"use strict";
|
||||||
|
|
||||||
const UrlJoin = require("url-join")
|
const UrlJoin = require("url-join");
|
||||||
import { AzureSearch } from "pragmatismo-io-framework"
|
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 { KBService } from "./../../kb.gbapp/services/KBService";
|
||||||
import { BotAdapter } from "botbuilder"
|
import { BotAdapter } from "botbuilder";
|
||||||
|
import { GBAdminService } from "../services/GBAdminService";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogs for administration tasks.
|
* Dialogs for administration tasks.
|
||||||
*/
|
*/
|
||||||
export class AdminDialog extends IGBDialog {
|
export class AdminDialog extends IGBDialog {
|
||||||
|
|
||||||
|
|
||||||
static async undeployPackageCommand(text: any, min: GBMinInstance, dc) {
|
static async undeployPackageCommand(text: any, min: GBMinInstance, dc) {
|
||||||
let packageName = text.split(" ")[1]
|
let packageName = text.split(" ")[1];
|
||||||
let importer = new GBImporter(min.core)
|
let importer = new GBImporter(min.core);
|
||||||
let deployer = new GBDeployer(min.core, importer)
|
let deployer = new GBDeployer(min.core, importer);
|
||||||
dc.context.sendActivity(`Undeploying package ${packageName}...`)
|
dc.context.sendActivity(`Undeploying package ${packageName}...`);
|
||||||
await deployer.undeployPackageFromLocalPath(
|
await deployer.undeployPackageFromLocalPath(
|
||||||
min.instance,
|
min.instance,
|
||||||
UrlJoin("deploy", packageName))
|
UrlJoin("deploy", packageName)
|
||||||
dc.context.sendActivity(`Package ${packageName} undeployed...`)
|
);
|
||||||
|
dc.context.sendActivity(`Package ${packageName} undeployed...`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async deployPackageCommand(
|
static async deployPackageCommand(
|
||||||
|
@ -65,11 +65,17 @@ export class AdminDialog extends IGBDialog {
|
||||||
deployer: GBDeployer,
|
deployer: GBDeployer,
|
||||||
min: GBMinInstance
|
min: GBMinInstance
|
||||||
) {
|
) {
|
||||||
let packageName = text.split(" ")[1]
|
let packageName = text.split(" ")[1];
|
||||||
await dc.context.sendActivity(`Deploying package ${packageName}... (It may take a few seconds)`)
|
await dc.context.sendActivity(
|
||||||
let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH")
|
`Deploying package ${packageName}... (It may take a few seconds)`
|
||||||
await deployer.deployPackageFromLocalPath(UrlJoin(additionalPath, packageName))
|
);
|
||||||
await dc.context.sendActivity(`Package ${packageName} deployed... Please run rebuildIndex command.`)
|
let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH");
|
||||||
|
await deployer.deployPackageFromLocalPath(
|
||||||
|
UrlJoin(additionalPath, packageName)
|
||||||
|
);
|
||||||
|
await dc.context.sendActivity(
|
||||||
|
`Package ${packageName} deployed... Please run rebuildIndex command.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async rebuildIndexCommand(min: GBMinInstance, dc) {
|
static async rebuildIndexCommand(min: GBMinInstance, dc) {
|
||||||
|
@ -78,12 +84,15 @@ export class AdminDialog extends IGBDialog {
|
||||||
min.instance.searchHost,
|
min.instance.searchHost,
|
||||||
min.instance.searchIndex,
|
min.instance.searchIndex,
|
||||||
min.instance.searchIndexer
|
min.instance.searchIndexer
|
||||||
)
|
);
|
||||||
dc.context.sendActivity("Rebuilding index...")
|
dc.context.sendActivity("Rebuilding index...");
|
||||||
await search.deleteIndex()
|
await search.deleteIndex();
|
||||||
let kbService = new KBService(min.core.sequelize)
|
let kbService = new KBService(min.core.sequelize);
|
||||||
await search.createIndex(kbService.getSearchSchema(min.instance.searchIndex), "gb")
|
await search.createIndex(
|
||||||
await dc.context.sendActivity("Index rebuilt.")
|
kbService.getSearchSchema(min.instance.searchIndex),
|
||||||
|
"gb"
|
||||||
|
);
|
||||||
|
await dc.context.sendActivity("Index rebuilt.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,80 +102,102 @@ export class AdminDialog extends IGBDialog {
|
||||||
* @param min The minimal bot instance data.
|
* @param min The minimal bot instance data.
|
||||||
*/
|
*/
|
||||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||||
|
|
||||||
// Setup services.
|
// Setup services.
|
||||||
|
|
||||||
let importer = new GBImporter(min.core)
|
let importer = new GBImporter(min.core);
|
||||||
let deployer = new GBDeployer(min.core, importer)
|
let deployer = new GBDeployer(min.core, importer);
|
||||||
|
|
||||||
min.dialogs.add("/admin", [
|
min.dialogs.add("/admin", [
|
||||||
|
async dc => {
|
||||||
|
await AdminDialog.refreshAdminToken(min, dc);
|
||||||
|
// await dc.context.sendActivity(
|
||||||
|
// `Deploying package ... (It may take a few seconds)`
|
||||||
|
// );
|
||||||
|
// await AdminDialog.deployPackageCommand(
|
||||||
|
// "deployPackage ProjectOnline.gbkb",
|
||||||
|
// dc,
|
||||||
|
// deployer,
|
||||||
|
// min
|
||||||
|
// );
|
||||||
|
await dc.endAll();
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
async (dc) => {
|
min.dialogs.add("/adminUpdateToken", [
|
||||||
|
async (dc, args, next) => {
|
||||||
await dc.context.sendActivity(`Deploying package ... (It may take a few seconds)`)
|
await dc.endAll();
|
||||||
await AdminDialog.deployPackageCommand("deployPackage ProjectOnline.gbkb", dc, deployer, min)
|
let service = new GBAdminService();
|
||||||
await dc.endAll()
|
await service.saveValue("authenticatorToken", args.token)
|
||||||
|
await dc.context.sendActivity("Token has been updated.");
|
||||||
}])
|
await dc.replace("/ask")
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
min.dialogs.add("/admin1", [
|
min.dialogs.add("/admin1", [
|
||||||
|
|
||||||
async (dc, args) => {
|
async (dc, args) => {
|
||||||
const prompt = "Please, authenticate:"
|
const prompt = "Please, authenticate:";
|
||||||
await dc.prompt('textPrompt', prompt)
|
await dc.prompt("textPrompt", prompt);
|
||||||
},
|
},
|
||||||
async (dc, value) => {
|
async (dc, value) => {
|
||||||
let text = value
|
let text = value;
|
||||||
const user = min.userState.get(dc.context)
|
const user = min.userState.get(dc.context);
|
||||||
|
|
||||||
if (
|
if (!user.authenticated || text === GBConfigService.get("ADMIN_PASS")) {
|
||||||
!user.authenticated ||
|
user.authenticated = true;
|
||||||
text === GBConfigService.get("ADMIN_PASS")
|
|
||||||
) {
|
|
||||||
user.authenticated = true
|
|
||||||
await dc.context.sendActivity(
|
await dc.context.sendActivity(
|
||||||
"Welcome to Pragmatismo.io GeneralBots Administration."
|
"Welcome to Pragmatismo.io GeneralBots Administration."
|
||||||
)
|
);
|
||||||
await dc.prompt('textPrompt', "Which task do you wanna run now?")
|
await dc.prompt("textPrompt", "Which task do you wanna run now?");
|
||||||
} else {
|
} else {
|
||||||
await dc.endAll()
|
await dc.endAll();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async (dc, value) => {
|
async (dc, value) => {
|
||||||
var text = value
|
var text = value;
|
||||||
const user = min.userState.get(dc.context)
|
const user = min.userState.get(dc.context);
|
||||||
|
|
||||||
if (text === "quit") {
|
if (text === "quit") {
|
||||||
user.authenticated = false
|
user.authenticated = false;
|
||||||
await dc.replace("/")
|
await dc.replace("/");
|
||||||
} else if (text === "sync") {
|
} else if (text === "sync") {
|
||||||
await min.core.syncDatabaseStructure()
|
await min.core.syncDatabaseStructure();
|
||||||
await dc.context.sendActivity("Sync started...")
|
await dc.context.sendActivity("Sync started...");
|
||||||
await dc.replace("/admin", { firstRun: false })
|
await dc.replace("/admin", { firstRun: false });
|
||||||
} else if (text.split(" ")[0] === "rebuildIndex") {
|
} else if (text.split(" ")[0] === "rebuildIndex") {
|
||||||
await AdminDialog.rebuildIndexCommand(min, dc)
|
await AdminDialog.rebuildIndexCommand(min, dc);
|
||||||
await dc.replace("/admin", { firstRun: false })
|
await dc.replace("/admin", { firstRun: false });
|
||||||
} else if (text.split(" ")[0] === "deployPackage") {
|
} else if (text.split(" ")[0] === "deployPackage") {
|
||||||
await AdminDialog.deployPackageCommand(text, dc, deployer, min)
|
await AdminDialog.deployPackageCommand(text, dc, deployer, min);
|
||||||
await dc.replace("/admin", { firstRun: false })
|
await dc.replace("/admin", { firstRun: false });
|
||||||
} else if (text.split(" ")[0] === "redeployPackage") {
|
} else if (text.split(" ")[0] === "redeployPackage") {
|
||||||
await AdminDialog.undeployPackageCommand(text, min, dc)
|
await AdminDialog.undeployPackageCommand(text, min, dc);
|
||||||
await AdminDialog.deployPackageCommand(text, dc, deployer, min)
|
await AdminDialog.deployPackageCommand(text, dc, deployer, min);
|
||||||
await dc.context.sendActivity("Redeploy done.")
|
await dc.context.sendActivity("Redeploy done.");
|
||||||
await dc.replace("/admin", { firstRun: false })
|
await dc.replace("/admin", { firstRun: false });
|
||||||
} else if (text.split(" ")[0] === "undeployPackage") {
|
} else if (text.split(" ")[0] === "undeployPackage") {
|
||||||
await AdminDialog.undeployPackageCommand(text, min, dc)
|
await AdminDialog.undeployPackageCommand(text, min, dc);
|
||||||
await dc.replace("/admin", { firstRun: false })
|
await dc.replace("/admin", { firstRun: false });
|
||||||
} else if (text.split(" ")[0] === "applyPackage") {
|
} else if (text.split(" ")[0] === "applyPackage") {
|
||||||
await dc.context.sendActivity("Applying in progress...")
|
await dc.context.sendActivity("Applying in progress...");
|
||||||
await min.core.loadInstance(text.split(" ")[1])
|
await min.core.loadInstance(text.split(" ")[1]);
|
||||||
await dc.context.sendActivity("Applying done...")
|
await dc.context.sendActivity("Applying done...");
|
||||||
await dc.replace("/admin", { firstRun: false })
|
await dc.replace("/admin", { firstRun: false });
|
||||||
} else if (text.split(" ")[0] === "rat") {
|
} else if (text.split(" ")[0] === "rat") {
|
||||||
await min.conversationalService.sendEvent(dc, "play", { playerType: "login", data: null })
|
await AdminDialog.refreshAdminToken(min, dc);
|
||||||
await dc.context.sendActivity("Realize login clicando no botão de login, por favor...")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async refreshAdminToken(min: any, dc: any) {
|
||||||
|
let config = {
|
||||||
|
authenticatorTenant: min.instance.authenticatorTenant,
|
||||||
|
authenticatorClientID: min.instance.authenticatorClientID
|
||||||
|
};
|
||||||
|
await min.conversationalService.sendEvent(dc, "play", {
|
||||||
|
playerType: "login",
|
||||||
|
data: config
|
||||||
|
});
|
||||||
|
await dc.context.sendActivity("Update your Administrative token by Login...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,15 @@ import { AdminDialog } from './dialogs/AdminDialog'
|
||||||
import { GBMinInstance, IGBPackage, IGBCoreService } from 'botlib'
|
import { GBMinInstance, IGBPackage, IGBCoreService } from 'botlib'
|
||||||
|
|
||||||
import { Sequelize } from 'sequelize-typescript'
|
import { Sequelize } from 'sequelize-typescript'
|
||||||
|
import { GuaribasAdmin } from './models/AdminModel';
|
||||||
|
|
||||||
export class GBAdminPackage implements IGBPackage {
|
export class GBAdminPackage implements IGBPackage {
|
||||||
sysPackages: IGBPackage[] = null
|
sysPackages: IGBPackage[] = null
|
||||||
|
|
||||||
loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
|
loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
|
||||||
|
core.sequelize.addModels([
|
||||||
|
GuaribasAdmin
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
unloadPackage(core: IGBCoreService): void {
|
unloadPackage(core: IGBCoreService): void {
|
||||||
|
|
61
deploy/admin.gbapp/models/AdminModel.ts
Normal file
61
deploy/admin.gbapp/models/AdminModel.ts
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*****************************************************************************\
|
||||||
|
| ( )_ _ |
|
||||||
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||||
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
|
||||||
|
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
|
||||||
|
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
||||||
|
| | | ( )_) | |
|
||||||
|
| (_) \___/' |
|
||||||
|
| |
|
||||||
|
| 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 {
|
||||||
|
Table,
|
||||||
|
Column,
|
||||||
|
Model,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
} from "sequelize-typescript";
|
||||||
|
|
||||||
|
|
||||||
|
@Table
|
||||||
|
export class GuaribasAdmin extends Model<GuaribasAdmin>
|
||||||
|
{
|
||||||
|
|
||||||
|
@Column
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@CreatedAt
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@UpdatedAt
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
57
deploy/admin.gbapp/services/GBAdminService.ts
Normal file
57
deploy/admin.gbapp/services/GBAdminService.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*****************************************************************************\
|
||||||
|
| ( )_ _ |
|
||||||
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||||
|
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
|
||||||
|
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
|
||||||
|
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
||||||
|
| | | ( )_) | |
|
||||||
|
| (_) \___/' |
|
||||||
|
| |
|
||||||
|
| 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 { GuaribasAdmin } from "../models/AdminModel";
|
||||||
|
|
||||||
|
export class GBAdminService {
|
||||||
|
|
||||||
|
async saveValue(key: string, value: string): Promise<GuaribasAdmin> {
|
||||||
|
let options = { where: {} }
|
||||||
|
options.where = { key: key }
|
||||||
|
let admin = await GuaribasAdmin.findOne(options);
|
||||||
|
if (admin == null) {
|
||||||
|
admin = new GuaribasAdmin();
|
||||||
|
admin.key = key;
|
||||||
|
}
|
||||||
|
admin.value = value;
|
||||||
|
return admin.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
async getValue(key: string) {
|
||||||
|
let options = { where: {} }
|
||||||
|
options.where = { key: key }
|
||||||
|
let obj = await GuaribasAdmin.findOne(options);
|
||||||
|
return Promise.resolve(obj.value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,14 +54,15 @@ export class WelcomeDialog extends IGBDialog {
|
||||||
user.once = true;
|
user.once = true;
|
||||||
var a = new Date();
|
var a = new Date();
|
||||||
const date = a.getHours();
|
const date = a.getHours();
|
||||||
var msg = 4;
|
var msg =
|
||||||
date < 12
|
date < 12
|
||||||
? Messages[locale].good_morning
|
? Messages[locale].good_morning
|
||||||
: date < 18
|
: date < 18
|
||||||
? Messages[locale].good_evening
|
? Messages[locale].good_evening
|
||||||
: Messages[locale].good_night;
|
: Messages[locale].good_night;
|
||||||
|
|
||||||
await dc.context.sendActivity(Messages[locale].hi(msg));
|
await dc.context.sendActivity(Messages[locale].hi(msg));
|
||||||
|
await dc.replace("/ask", { firstTime: true });
|
||||||
|
|
||||||
if (
|
if (
|
||||||
dc.context.activity &&
|
dc.context.activity &&
|
||||||
|
|
|
@ -30,14 +30,14 @@
|
||||||
| |
|
| |
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
"use strict"
|
"use strict";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DataTypes,
|
DataTypes,
|
||||||
DataTypeUUIDv4,
|
DataTypeUUIDv4,
|
||||||
DataTypeDate,
|
DataTypeDate,
|
||||||
DataTypeDecimal
|
DataTypeDecimal
|
||||||
} from "sequelize"
|
} from "sequelize";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Sequelize,
|
Sequelize,
|
||||||
|
@ -54,170 +54,214 @@ import {
|
||||||
DataType,
|
DataType,
|
||||||
PrimaryKey,
|
PrimaryKey,
|
||||||
AutoIncrement
|
AutoIncrement
|
||||||
} from "sequelize-typescript"
|
} from "sequelize-typescript";
|
||||||
|
|
||||||
import { IGBInstance } from "botlib"
|
import { IGBInstance } from "botlib";
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasInstance extends Model<GuaribasInstance> implements IGBInstance {
|
export class GuaribasInstance extends Model<GuaribasInstance>
|
||||||
|
implements IGBInstance {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column
|
@Column
|
||||||
instanceId: number
|
instanceId: number;
|
||||||
|
|
||||||
@Column applicationPrincipal: string
|
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
whoAmIVideo: string
|
applicationPrincipal: string;
|
||||||
|
|
||||||
@Column botId: string
|
@Column
|
||||||
|
whoAmIVideo: string;
|
||||||
|
|
||||||
@Column title: string
|
@Column
|
||||||
|
botId: string;
|
||||||
|
|
||||||
@Column description: string
|
@Column
|
||||||
|
title: string;
|
||||||
|
|
||||||
@Column version: string
|
@Column
|
||||||
|
description: string;
|
||||||
|
|
||||||
@Column enabledAdmin: boolean
|
@Column
|
||||||
|
version: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
enabledAdmin: boolean;
|
||||||
|
|
||||||
/* Services section on bot.json */
|
/* Services section on bot.json */
|
||||||
|
|
||||||
@Column engineName: string
|
@Column
|
||||||
|
engineName: string;
|
||||||
@Column marketplaceId: string
|
|
||||||
|
|
||||||
@Column textAnalyticsKey: string
|
|
||||||
|
|
||||||
@Column textAnalyticsServerUrl: string
|
|
||||||
|
|
||||||
@Column marketplacePassword: string
|
|
||||||
|
|
||||||
@Column webchatKey: string
|
|
||||||
|
|
||||||
@Column whatsappBotKey: string
|
|
||||||
|
|
||||||
@Column whatsappServiceKey: string
|
|
||||||
|
|
||||||
@Column whatsappServiceNumber: string
|
|
||||||
|
|
||||||
@Column whatsappServiceUrl: string
|
|
||||||
|
|
||||||
@Column whatsappServiceWebhookUrl: string
|
|
||||||
|
|
||||||
@Column speechKey: string
|
|
||||||
|
|
||||||
@Column spellcheckerKey: string
|
|
||||||
|
|
||||||
@Column theme: string
|
|
||||||
|
|
||||||
@Column ui: string
|
|
||||||
|
|
||||||
@Column kb: string
|
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
nlpAppId: string
|
marketplaceId: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
nlpSubscriptionKey: string
|
textAnalyticsKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
textAnalyticsServerUrl: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
marketplacePassword: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
webchatKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
authenticatorTenant: string;
|
||||||
|
@Column
|
||||||
|
authenticatorSignUpSignInPolicy: string;
|
||||||
|
@Column
|
||||||
|
authenticatorClientID: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
whatsappBotKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
whatsappServiceKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
whatsappServiceNumber: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
whatsappServiceUrl: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
whatsappServiceWebhookUrl: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
smsKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
smsSecret: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
smsServiceNumber: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
speechKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
spellcheckerKey: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
theme: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
ui: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
kb: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
nlpAppId: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
nlpSubscriptionKey: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Column({ type: DataType.STRING(512) })
|
@Column({ type: DataType.STRING(512) })
|
||||||
nlpServerUrl: string
|
nlpServerUrl: string;
|
||||||
|
|
||||||
@Column searchHost: string
|
@Column
|
||||||
|
searchHost: string;
|
||||||
|
|
||||||
@Column searchKey: string
|
@Column
|
||||||
|
searchKey: string;
|
||||||
|
|
||||||
@Column searchIndex: string
|
@Column
|
||||||
|
searchIndex: string;
|
||||||
|
|
||||||
@Column searchIndexer: string
|
@Column
|
||||||
|
searchIndexer: string;
|
||||||
|
|
||||||
/* Settings section of bot.json */
|
/* Settings section of bot.json */
|
||||||
|
|
||||||
@Column(DataType.FLOAT) nlpVsSearch: number
|
@Column(DataType.FLOAT)
|
||||||
|
nlpVsSearch: number;
|
||||||
|
|
||||||
@Column(DataType.FLOAT) searchScore: number
|
@Column(DataType.FLOAT)
|
||||||
|
searchScore: number;
|
||||||
|
|
||||||
@Column(DataType.FLOAT) nlpScore: number
|
@Column(DataType.FLOAT)
|
||||||
|
nlpScore: number;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
updatedAt: Date
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasPackage extends Model<GuaribasPackage> {
|
export class GuaribasPackage extends Model<GuaribasPackage> {
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column
|
@Column
|
||||||
packageId: number
|
packageId: number;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
packageName: string
|
packageName: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column
|
@Column
|
||||||
instanceId: number
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
instance: GuaribasInstance
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
updatedAt: Date
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasChannel extends Model<GuaribasChannel> {
|
export class GuaribasChannel extends Model<GuaribasChannel> {
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column
|
@Column
|
||||||
channelId: number
|
channelId: number;
|
||||||
|
|
||||||
@Column title: string
|
@Column
|
||||||
|
title: string;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
updatedAt: Date
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export class GuaribasException extends Model<GuaribasException> {
|
export class GuaribasException extends Model<GuaribasException> {
|
||||||
|
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column
|
@Column
|
||||||
exceptionId: number
|
exceptionId: number;
|
||||||
|
|
||||||
@Column message: string
|
@Column
|
||||||
|
message: string;
|
||||||
|
|
||||||
@ForeignKey(() => GuaribasInstance)
|
@ForeignKey(() => GuaribasInstance)
|
||||||
@Column
|
@Column
|
||||||
instanceId: number
|
instanceId: number;
|
||||||
|
|
||||||
@BelongsTo(() => GuaribasInstance)
|
@BelongsTo(() => GuaribasInstance)
|
||||||
instance: GuaribasInstance
|
instance: GuaribasInstance;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdAt: Date
|
createdAt: Date;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
updatedAt: Date
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { IGBInstance } from 'botlib';
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
| ( )_ _ |
|
| ( )_ _ |
|
||||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||||
|
@ -41,6 +42,8 @@ import { LuisRecognizer } from "botbuilder-ai";
|
||||||
import { MessageFactory } from "botbuilder";
|
import { MessageFactory } from "botbuilder";
|
||||||
import { Messages } from "../strings";
|
import { Messages } from "../strings";
|
||||||
import { AzureText } from "pragmatismo-io-framework";
|
import { AzureText } from "pragmatismo-io-framework";
|
||||||
|
const Nexmo = require("nexmo");
|
||||||
|
|
||||||
|
|
||||||
export interface LanguagePickerSettings {
|
export interface LanguagePickerSettings {
|
||||||
defaultLocale?: string;
|
defaultLocale?: string;
|
||||||
|
@ -66,6 +69,19 @@ export class GBConversationalService implements IGBConversationalService {
|
||||||
return dc.context.sendActivity(msg);
|
return dc.context.sendActivity(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async sendSms(min: GBMinInstance, mobile: string, text: string) : Promise<any> {
|
||||||
|
const nexmo = new Nexmo({
|
||||||
|
apiKey: min.instance.smsKey,
|
||||||
|
apiSecret: min.instance.smsSecret,
|
||||||
|
});
|
||||||
|
nexmo.message.sendSms(
|
||||||
|
min.instance.smsServiceNumber,
|
||||||
|
mobile,
|
||||||
|
text,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async routeNLP(dc: any, min: GBMinInstance, text: string): Promise<boolean> {
|
async routeNLP(dc: any, min: GBMinInstance, text: string): Promise<boolean> {
|
||||||
// Invokes LUIS.
|
// Invokes LUIS.
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ 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";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core service layer.
|
* Core service layer.
|
||||||
|
@ -47,6 +48,11 @@ export class GBCoreService implements IGBCoreService {
|
||||||
*/
|
*/
|
||||||
public sequelize: Sequelize
|
public sequelize: Sequelize
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Administrative services.
|
||||||
|
*/
|
||||||
|
public adminService: GBAdminService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows filtering on SQL generated before send to the database.
|
* Allows filtering on SQL generated before send to the database.
|
||||||
*/
|
*/
|
||||||
|
@ -72,6 +78,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.dialect = GBConfigService.get("DATABASE_DIALECT")
|
this.dialect = GBConfigService.get("DATABASE_DIALECT")
|
||||||
|
this.adminService = new GBAdminService();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,8 +105,8 @@ export class GBCoreService implements IGBCoreService {
|
||||||
let logging =
|
let logging =
|
||||||
GBConfigService.get("DATABASE_LOGGING") === "true"
|
GBConfigService.get("DATABASE_LOGGING") === "true"
|
||||||
? (str: string) => {
|
? (str: string) => {
|
||||||
logger.info(str)
|
logger.info(str)
|
||||||
}
|
}
|
||||||
: false
|
: false
|
||||||
|
|
||||||
let encrypt = GBConfigService.get("DATABASE_ENCRYPT") === "true"
|
let encrypt = GBConfigService.get("DATABASE_ENCRYPT") === "true"
|
||||||
|
@ -240,79 +247,38 @@ export class GBCoreService implements IGBCoreService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async syncDatabaseStructure() {
|
async syncDatabaseStructure() {
|
||||||
return new Promise((resolve, reject) => {
|
if (GBConfigService.get("DATABASE_SYNC") === "true") {
|
||||||
if (GBConfigService.get("DATABASE_SYNC") === "true") {
|
const alter = GBConfigService.get("DATABASE_SYNC_ALTER") === "true"
|
||||||
const alter = GBConfigService.get("DATABASE_SYNC_ALTER") === "true"
|
const force = GBConfigService.get("DATABASE_SYNC_FORCE") === "true"
|
||||||
const force = GBConfigService.get("DATABASE_SYNC_FORCE") === "true"
|
logger.info("Syncing database...")
|
||||||
logger.info("Syncing database...")
|
return this.sequelize.sync({
|
||||||
this.sequelize
|
alter: alter,
|
||||||
.sync({
|
force: force
|
||||||
alter: alter,
|
});
|
||||||
force: force
|
} else {
|
||||||
})
|
let msg = "Database synchronization is disabled.";
|
||||||
.then(
|
logger.info(msg)
|
||||||
value => {
|
return Promise.reject(msg)
|
||||||
logger.info("Database synced.")
|
}
|
||||||
resolve(value)
|
|
||||||
},
|
|
||||||
err => reject(err)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
logger.info("Database synchronization is disabled.")
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all items to start several listeners.
|
* Loads all items to start several listeners.
|
||||||
*/
|
*/
|
||||||
async loadInstances(): Promise<IGBInstance> {
|
async loadInstances(): Promise<IGBInstance> {
|
||||||
return new Promise((resolve, reject) => {
|
return GuaribasInstance.findAll({});
|
||||||
GuaribasInstance.findAll({})
|
|
||||||
.then((items: IGBInstance[]) => {
|
|
||||||
if (!items) items = []
|
|
||||||
|
|
||||||
if (items.length == 0) {
|
|
||||||
resolve([])
|
|
||||||
} else {
|
|
||||||
resolve(items)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(reason => {
|
|
||||||
if (reason.message.indexOf("no such table: GuaribasInstance") != -1) {
|
|
||||||
resolve([])
|
|
||||||
} else {
|
|
||||||
logger.info(`GuaribasServiceError: ${reason}`)
|
|
||||||
reject(reason)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads just one Bot instance.
|
* Loads just one Bot instance.
|
||||||
*/
|
*/
|
||||||
async loadInstance(botId: string): Promise<IGBInstance> {
|
async loadInstance(botId: string): Promise<IGBInstance> {
|
||||||
return new Promise<IGBInstance>((resolve, reject) => {
|
let options = { where: {} }
|
||||||
let options = { where: {} }
|
|
||||||
|
|
||||||
if (botId != "[default]") {
|
if (botId != "[default]") {
|
||||||
options.where = { botId: botId }
|
options.where = { botId: botId }
|
||||||
}
|
}
|
||||||
|
|
||||||
GuaribasInstance.findOne(options)
|
return GuaribasInstance.findOne(options);
|
||||||
.then((instance: IGBInstance) => {
|
|
||||||
if (instance) {
|
|
||||||
resolve(instance)
|
|
||||||
} else {
|
|
||||||
resolve(null)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
logger.info(`GuaribasServiceError: ${err}`)
|
|
||||||
reject(err)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ export class GBDeployer {
|
||||||
appPackagesProcessed++
|
appPackagesProcessed++
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
logger.info(`Error deploying App (.gbapp): ${e}: ${err}`)
|
logger.error(`Error deploying App (.gbapp): ${e}: ${err}`)
|
||||||
appPackagesProcessed++
|
appPackagesProcessed++
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,14 +145,16 @@ export class GBDeployer {
|
||||||
WaitUntil()
|
WaitUntil()
|
||||||
.interval(1000)
|
.interval(1000)
|
||||||
.times(10)
|
.times(10)
|
||||||
.condition(function(cb) {
|
.condition(function (cb) {
|
||||||
logger.info(`Waiting for app package deployment...`)
|
logger.info(`Waiting for app package deployment...`)
|
||||||
cb(appPackagesProcessed == gbappPackages.length)
|
cb(appPackagesProcessed == gbappPackages.length)
|
||||||
})
|
})
|
||||||
.done(function(result) {
|
.done(function (result) {
|
||||||
logger.info(`App Package deployment done.`)
|
logger.info(`App Package deployment done.`);
|
||||||
|
|
||||||
core.syncDatabaseStructure()
|
(async () => {
|
||||||
|
await core.syncDatabaseStructure()
|
||||||
|
})()
|
||||||
|
|
||||||
/** Deploys all .gbot files first. */
|
/** Deploys all .gbot files first. */
|
||||||
|
|
||||||
|
@ -179,7 +181,7 @@ export class GBDeployer {
|
||||||
server.use("/themes/" + filenameOnly, express.static(filename))
|
server.use("/themes/" + filenameOnly, express.static(filename))
|
||||||
logger.info(
|
logger.info(
|
||||||
`Theme (.gbtheme) assets accessible at: ${"/themes/" +
|
`Theme (.gbtheme) assets accessible at: ${"/themes/" +
|
||||||
filenameOnly}.`
|
filenameOnly}.`
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Knowledge base for bots. */
|
/** Knowledge base for bots. */
|
||||||
|
@ -205,13 +207,13 @@ export class GBDeployer {
|
||||||
})
|
})
|
||||||
|
|
||||||
WaitUntil()
|
WaitUntil()
|
||||||
.interval(1000)
|
.interval(100)
|
||||||
.times(5)
|
.times(5)
|
||||||
.condition(function(cb) {
|
.condition(function (cb) {
|
||||||
logger.info(`Waiting for package deployment...`)
|
logger.info(`Waiting for package deployment...`)
|
||||||
cb(totalPackages == generalPackages.length)
|
cb(totalPackages == generalPackages.length)
|
||||||
})
|
})
|
||||||
.done(function(result) {
|
.done(function (result) {
|
||||||
if (botPackages.length === 0) {
|
if (botPackages.length === 0) {
|
||||||
logger.info(
|
logger.info(
|
||||||
"The server is running with no bot instances, at least one .gbot file must be deployed."
|
"The server is running with no bot instances, at least one .gbot file must be deployed."
|
||||||
|
|
|
@ -136,7 +136,9 @@ export class GBMinService {
|
||||||
theme: instance.theme,
|
theme: instance.theme,
|
||||||
secret: instance.webchatKey, // TODO: Use token.
|
secret: instance.webchatKey, // TODO: Use token.
|
||||||
speechToken: speechToken,
|
speechToken: speechToken,
|
||||||
conversationId: webchatToken.conversationId
|
conversationId: webchatToken.conversationId,
|
||||||
|
authenticatorTenant: instance.authenticatorTenant,
|
||||||
|
authenticatorClientID: instance.authenticatorClientID
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -270,97 +272,105 @@ export class GBMinService {
|
||||||
appPackages: any[]
|
appPackages: any[]
|
||||||
) {
|
) {
|
||||||
return adapter.processActivity(req, res, async context => {
|
return adapter.processActivity(req, res, async context => {
|
||||||
const state = conversationState.get(context)
|
|
||||||
const dc = min.dialogs.createContext(context, state)
|
|
||||||
dc.context.activity.locale = "en-US"
|
|
||||||
const user = min.userState.get(dc.context)
|
|
||||||
|
|
||||||
if (!user.loaded) {
|
try {
|
||||||
await min.conversationalService.sendEvent(dc, "loadInstance", {
|
const state = conversationState.get(context)
|
||||||
instanceId: instance.instanceId,
|
const dc = min.dialogs.createContext(context, state)
|
||||||
botId: instance.botId,
|
dc.context.activity.locale = "en-US"
|
||||||
theme: instance.theme,
|
const user = min.userState.get(dc.context)
|
||||||
secret: instance.webchatKey
|
|
||||||
})
|
|
||||||
user.loaded = true
|
|
||||||
user.subjects = []
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info(
|
if (!user.loaded) {
|
||||||
`[RCV]: ${context.activity.type}, ChannelID: ${
|
await min.conversationalService.sendEvent(dc, "loadInstance", {
|
||||||
|
instanceId: instance.instanceId,
|
||||||
|
botId: instance.botId,
|
||||||
|
theme: instance.theme,
|
||||||
|
secret: instance.webchatKey
|
||||||
|
})
|
||||||
|
user.loaded = true
|
||||||
|
user.subjects = []
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
`[RCV]: ${context.activity.type}, ChannelID: ${
|
||||||
context.activity.channelId
|
context.activity.channelId
|
||||||
}, Name: ${context.activity.name}, Text: ${context.activity.text}.`
|
}, Name: ${context.activity.name}, Text: ${context.activity.text}.`
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
context.activity.type === "conversationUpdate" &&
|
context.activity.type === "conversationUpdate" &&
|
||||||
context.activity.membersAdded.length > 0
|
context.activity.membersAdded.length > 0
|
||||||
) {
|
) {
|
||||||
|
|
||||||
let member = context.activity.membersAdded[0]
|
let member = context.activity.membersAdded[0]
|
||||||
if (member.name === "GeneralBots") {
|
if (member.name === "GeneralBots") {
|
||||||
logger.info(`Bot added to conversation, starting chat...`)
|
logger.info(`Bot added to conversation, starting chat...`)
|
||||||
appPackages.forEach(e => {
|
appPackages.forEach(e => {
|
||||||
e.onNewSession(min, dc)
|
e.onNewSession(min, dc)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Starts root dialog.
|
// Processes the root dialog.
|
||||||
|
|
||||||
await dc.begin("/")
|
await dc.begin("/")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.info(`Member added to conversation: ${member.name}`)
|
logger.info(`Member added to conversation: ${member.name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes messages.
|
// Processes messages.
|
||||||
|
|
||||||
} else if (context.activity.type === "message") {
|
} else if (context.activity.type === "message") {
|
||||||
|
|
||||||
// Checks for /admin request.
|
// Checks for /admin request.
|
||||||
|
|
||||||
if (context.activity.text === "admin") {
|
if (context.activity.text === "admin") {
|
||||||
await dc.begin("/admin")
|
await dc.begin("/admin")
|
||||||
|
|
||||||
// Checks for /menu JSON signature.
|
// Checks for /menu JSON signature.
|
||||||
|
|
||||||
} else if (context.activity.text.startsWith("{\"title\"")) {
|
} else if (context.activity.text.startsWith("{\"title\"")) {
|
||||||
await dc.begin("/menu", {data:JSON.parse(context.activity.text)})
|
await dc.begin("/menu", { data: JSON.parse(context.activity.text) })
|
||||||
|
|
||||||
// Otherwise, continue to the active dialog in the stack.
|
// Otherwise, continue to the active dialog in the stack.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
await dc.continue()
|
await dc.continue()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes events.
|
// Processes events.
|
||||||
|
|
||||||
} else if (context.activity.type === "event") {
|
} else if (context.activity.type === "event") {
|
||||||
|
|
||||||
// Empties dialog stack before going to the target.
|
// Empties dialog stack before going to the target.
|
||||||
|
|
||||||
await dc.endAll()
|
await dc.endAll()
|
||||||
|
|
||||||
if (context.activity.name === "whoAmI") {
|
if (context.activity.name === "whoAmI") {
|
||||||
await dc.begin("/whoAmI")
|
await dc.begin("/whoAmI")
|
||||||
} else if (context.activity.name === "showSubjects") {
|
} else if (context.activity.name === "showSubjects") {
|
||||||
await dc.begin("/menu")
|
await dc.begin("/menu")
|
||||||
} else if (context.activity.name === "giveFeedback") {
|
} else if (context.activity.name === "giveFeedback") {
|
||||||
await dc.begin("/feedback", {
|
await dc.begin("/feedback", {
|
||||||
fromMenu: true
|
fromMenu: true
|
||||||
})
|
})
|
||||||
} else if (context.activity.name === "showFAQ") {
|
} else if (context.activity.name === "showFAQ") {
|
||||||
await dc.begin("/faq")
|
await dc.begin("/faq")
|
||||||
} else if (context.activity.name === "ask") {
|
} else if (context.activity.name === "ask") {
|
||||||
await dc.begin("/answer", {
|
await dc.begin("/answer", {
|
||||||
query: (context.activity as any).data,
|
query: (context.activity as any).data,
|
||||||
fromFaq: true
|
fromFaq: true
|
||||||
})
|
})
|
||||||
} else if (context.activity.name === "quality") {
|
|
||||||
await dc.begin("/quality", {
|
} else if (context.activity.name === "quality") {
|
||||||
// TODO: score: context.activity.data
|
await dc.begin("/quality", { score: (context.activity as any).data })
|
||||||
})
|
} else if (context.activity.name === "updateToken") {
|
||||||
} else {
|
let token = (context.activity as any).data
|
||||||
await dc.continue()
|
await dc.begin("/adminUpdateToken", { token: token })
|
||||||
|
} else {
|
||||||
|
await dc.continue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
let msg = `Error in main activity: ${error}.`
|
||||||
|
logger.error(msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,4 +55,6 @@
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -45,6 +45,7 @@ import { SpeechSynthesizer } from "botframework-webchat/CognitiveServices";
|
||||||
import { SynthesisGender } from "botframework-webchat/CognitiveServices";
|
import { SynthesisGender } from "botframework-webchat/CognitiveServices";
|
||||||
import { Chat } from "botframework-webchat";
|
import { Chat } from "botframework-webchat";
|
||||||
import GBPowerBIPlayer from "./players/GBPowerBIPlayer.js";
|
import GBPowerBIPlayer from "./players/GBPowerBIPlayer.js";
|
||||||
|
import { UserAgentApplication } from "msal";
|
||||||
|
|
||||||
class GBUIApp extends React.Component {
|
class GBUIApp extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -58,6 +59,22 @@ class GBUIApp extends React.Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendToken(token) {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.botConnection
|
||||||
|
.postActivity({
|
||||||
|
type: "event",
|
||||||
|
name: "updateToken",
|
||||||
|
data: token,
|
||||||
|
locale: "en-us",
|
||||||
|
textFormat: "plain",
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
from: { id: "webUser", name: "You" }
|
||||||
|
})
|
||||||
|
.subscribe(this.send("success"));
|
||||||
|
}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
send(command) {
|
send(command) {
|
||||||
window.botConnection
|
window.botConnection
|
||||||
.postActivity({
|
.postActivity({
|
||||||
|
@ -93,8 +110,11 @@ class GBUIApp extends React.Component {
|
||||||
|
|
||||||
configureChat() {
|
configureChat() {
|
||||||
var botId = window.location.href.split("/")[3];
|
var botId = window.location.href.split("/")[3];
|
||||||
|
if (botId.indexOf('#') != -1) {
|
||||||
|
botId = botId.split("#")[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (!botId) {
|
if (!botId || botId == "") {
|
||||||
botId = "[default]";
|
botId = "[default]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +122,7 @@ class GBUIApp extends React.Component {
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(
|
.then(
|
||||||
result => {
|
result => {
|
||||||
this.setState({instanceClient:result});
|
this.setState({ instanceClient: result });
|
||||||
this.setupBotConnection();
|
this.setupBotConnection();
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
@ -114,6 +134,38 @@ class GBUIApp extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authenticate() {
|
||||||
|
let _this_ = this;
|
||||||
|
let authority =
|
||||||
|
"https://login.microsoftonline.com/" +
|
||||||
|
this.state.instanceClient.authenticatorTenant;
|
||||||
|
|
||||||
|
let graphScopes = ["Directory.AccessAsUser.All"];
|
||||||
|
|
||||||
|
let userAgentApplication = new UserAgentApplication(
|
||||||
|
this.state.instanceClient.authenticatorClientID,
|
||||||
|
authority,
|
||||||
|
function (errorDesc, token, error, tokenType) {
|
||||||
|
userAgentApplication.acquireTokenSilent(graphScopes).then(function (accessToken) {
|
||||||
|
_this_.sendToken(accessToken);
|
||||||
|
}, function (error) {
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!userAgentApplication.isCallback(window.location.hash) && window.parent === window && !window.opener) {
|
||||||
|
var user = userAgentApplication.getUser();
|
||||||
|
if (user) {
|
||||||
|
userAgentApplication.acquireTokenSilent(graphScopes).then(function (accessToken) {
|
||||||
|
_this_.sendToken(accessToken);
|
||||||
|
}, function (error) {
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setupBotConnection() {
|
setupBotConnection() {
|
||||||
let _this_ = this;
|
let _this_ = this;
|
||||||
window["botchatDebug"] = true;
|
window["botchatDebug"] = true;
|
||||||
|
@ -124,14 +176,13 @@ class GBUIApp extends React.Component {
|
||||||
|
|
||||||
botConnection.connectionStatus$.subscribe(connectionStatus => {
|
botConnection.connectionStatus$.subscribe(connectionStatus => {
|
||||||
if (connectionStatus === ConnectionStatus.Online) {
|
if (connectionStatus === ConnectionStatus.Online) {
|
||||||
|
_this_.setState({ botConnection: botConnection });
|
||||||
botConnection.postActivity({
|
botConnection.postActivity({
|
||||||
type: "event",
|
type: "event",
|
||||||
value: "startGB",
|
value: "startGB",
|
||||||
from: this.getUser(),
|
from: this.getUser(),
|
||||||
name: "startGB"
|
name: "startGB"
|
||||||
});
|
});
|
||||||
|
|
||||||
_this_.setState({ botConnection: botConnection });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -145,6 +196,7 @@ class GBUIApp extends React.Component {
|
||||||
)
|
)
|
||||||
.subscribe(activity => {
|
.subscribe(activity => {
|
||||||
_this_.setState({ instance: activity.value });
|
_this_.setState({ instance: activity.value });
|
||||||
|
_this_.authenticate()
|
||||||
});
|
});
|
||||||
|
|
||||||
botConnection.activity$
|
botConnection.activity$
|
||||||
|
@ -224,7 +276,7 @@ class GBUIApp extends React.Component {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "login":
|
case "login":
|
||||||
playerComponent = (
|
playerComponent = (
|
||||||
<GBLoginPlayer
|
<GBLoginPlayer
|
||||||
app={this}
|
app={this}
|
||||||
|
@ -246,7 +298,7 @@ class GBUIApp extends React.Component {
|
||||||
|
|
||||||
let speechOptions;
|
let speechOptions;
|
||||||
let chat = <div />;
|
let chat = <div />;
|
||||||
let gbCss =<div />;
|
let gbCss = <div />;
|
||||||
|
|
||||||
|
|
||||||
let sideBar = (
|
let sideBar = (
|
||||||
|
|
|
@ -39,3 +39,4 @@ ReactDOM.render(
|
||||||
<GBUIApp head={document.getElementsByTagName("head")[0]} />,
|
<GBUIApp head={document.getElementsByTagName("head")[0]} />,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -31,68 +31,54 @@
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { Logger, LogLevel } from "msal";
|
||||||
import { UserAgentApplication } from "msal";
|
import { UserAgentApplication } from "msal";
|
||||||
|
|
||||||
class GBLoginPlayer extends React.Component {
|
class GBLoginPlayer extends React.Component {
|
||||||
|
constructor() {
|
||||||
constructor(tenant) {
|
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
token: "",
|
login: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doLogin(info) {
|
||||||
|
let logger = new Logger(
|
||||||
login() {
|
(logLevel, message, piiEnabled) => {
|
||||||
|
console.log(message);
|
||||||
let config = {
|
},
|
||||||
tenant: "pragmatismo.onmicrosoft.com", //"6ecb2a67-15af-4582-ab85-cc65096ce471",
|
{ level: LogLevel.Verbose }
|
||||||
signUpSignInPolicy: "b2c_1_susi",
|
|
||||||
clientID: '47cbaa05-dbb4-46f8-8608-da386c5131f1'}
|
|
||||||
|
|
||||||
|
|
||||||
let authority = "https://login.microsoftonline.com/tfp/" +
|
|
||||||
config.tenant + "/" +
|
|
||||||
config.signUpSignInPolicy;
|
|
||||||
|
|
||||||
let userAgentApplication = new UserAgentApplication(
|
|
||||||
config.clientID, authority,
|
|
||||||
function (errorDesc, token, error, tokenType) {
|
|
||||||
console.log(token);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
let authority =
|
||||||
|
"https://login.microsoftonline.com/" +
|
||||||
|
this.state.login.authenticatorTenant;
|
||||||
|
|
||||||
let graphScopes = ["Directory.AccessAsUser.All"];
|
let graphScopes = ["Directory.AccessAsUser.All"];
|
||||||
|
|
||||||
userAgentApplication.loginPopup(graphScopes).then(function (idToken) {
|
let userAgentApplication = new UserAgentApplication(
|
||||||
userAgentApplication.acquireTokenSilent(graphScopes).then(function (accessToken) {
|
this.state.login.authenticatorClientID,
|
||||||
console.log(accessToken);
|
authority,
|
||||||
|
function (errorDesc, token, error, tokenType) {
|
||||||
}, function (error) {
|
if (error) {
|
||||||
userAgentApplication.acquireTokenPopup(graphScopes).then(function (accessToken) {
|
|
||||||
console.log(accessToken);
|
|
||||||
|
|
||||||
}, function (error) {
|
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
}
|
||||||
})
|
})
|
||||||
}, function (error) {
|
|
||||||
console.log(error);
|
userAgentApplication.loginRedirect(graphScopes);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
play() {
|
play(data) {
|
||||||
|
this.setState({ login: data });
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.setState({ login: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <button onClick={() => this.doLogin(this.state.login)}>Login</button>;
|
||||||
<button
|
|
||||||
value="Login"
|
|
||||||
onClick={this.login}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ import { BotAdapter } from "botbuilder";
|
||||||
import { Messages } from "../strings";
|
import { Messages } from "../strings";
|
||||||
import { LuisRecognizer } from "botbuilder-ai";
|
import { LuisRecognizer } from "botbuilder-ai";
|
||||||
|
|
||||||
|
|
||||||
const logger = require("../../../src/logger");
|
const logger = require("../../../src/logger");
|
||||||
|
|
||||||
export class AskDialog extends IGBDialog {
|
export class AskDialog extends IGBDialog {
|
||||||
|
@ -69,7 +68,7 @@ export class AskDialog extends IGBDialog {
|
||||||
throw new Error(`/answer being called with no args.query text.`);
|
throw new Error(`/answer being called with no args.query text.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let locale = dc.context.activity.locale
|
let locale = dc.context.activity.locale;
|
||||||
|
|
||||||
// Stops any content on projector.
|
// Stops any content on projector.
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ export class AskDialog extends IGBDialog {
|
||||||
);
|
);
|
||||||
await dc.replace("/ask", { isReturning: true });
|
await dc.replace("/ask", { isReturning: true });
|
||||||
} else {
|
} else {
|
||||||
if (!(await min.conversationalService.runNLP(dc, min, text))) {
|
if (!(await min.conversationalService.routeNLP(dc, min, text))) {
|
||||||
await dc.context.sendActivity(Messages[locale].did_not_find);
|
await dc.context.sendActivity(Messages[locale].did_not_find);
|
||||||
await dc.replace("/ask", { isReturning: true });
|
await dc.replace("/ask", { isReturning: true });
|
||||||
}
|
}
|
||||||
|
@ -181,16 +180,21 @@ export class AskDialog extends IGBDialog {
|
||||||
user.subjects = [];
|
user.subjects = [];
|
||||||
}
|
}
|
||||||
let text = [];
|
let text = [];
|
||||||
if (user.subjects.length > 0) {
|
|
||||||
text = Messages[locale].which_question;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args && args.isReturning) {
|
// Three forms of asking.
|
||||||
|
|
||||||
|
if (args.firstTime) {
|
||||||
|
text = Messages[locale].ask_first_time;
|
||||||
|
} else if (args && args.isReturning) {
|
||||||
text = Messages[locale].anything_else;
|
text = Messages[locale].anything_else;
|
||||||
|
} else if (user.subjects.length > 0) {
|
||||||
|
text = Messages[locale].which_question;
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid use of /ask");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.length > 0) {
|
if (text.length > 0) {
|
||||||
await dc.prompt("textPrompt", text[0]);
|
await dc.prompt("textPrompt", text);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async (dc, value) => {
|
async (dc, value) => {
|
||||||
|
|
|
@ -13,7 +13,9 @@ export const Messages = {
|
||||||
`Vamos pesquisar sobre ${query}... O que deseja saber?`,
|
`Vamos pesquisar sobre ${query}... O que deseja saber?`,
|
||||||
see_faq:
|
see_faq:
|
||||||
"Please take a look at the FAQ I've prepared for you. You can click on them to get the answer.",
|
"Please take a look at the FAQ I've prepared for you. You can click on them to get the answer.",
|
||||||
will_answer_projector:"I'll answer on the projector to a better experience..."
|
will_answer_projector:
|
||||||
|
"I'll answer on the projector to a better experience...",
|
||||||
|
ask_first_time: "What are you looking for?"
|
||||||
},
|
},
|
||||||
"pt-BR": {
|
"pt-BR": {
|
||||||
did_not_find: "Desculpe-me, não encontrei nada a respeito.",
|
did_not_find: "Desculpe-me, não encontrei nada a respeito.",
|
||||||
|
@ -29,6 +31,8 @@ export const Messages = {
|
||||||
`Let's search about ${query}... What do you want to know?`,
|
`Let's search about ${query}... What do you want to know?`,
|
||||||
see_faq:
|
see_faq:
|
||||||
"Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.",
|
"Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.",
|
||||||
will_answer_projector:"Vou te responder na tela para melhor visualização..."
|
will_answer_projector:
|
||||||
|
"Vou te responder na tela para melhor visualização...",
|
||||||
|
ask_first_time: "Sobre como eu poderia ajudar?"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,20 +42,22 @@
|
||||||
"botlib": "^0.0.33",
|
"botlib": "^0.0.33",
|
||||||
"chokidar": "^2.0.4",
|
"chokidar": "^2.0.4",
|
||||||
"csv-parse": "^3.0.0",
|
"csv-parse": "^3.0.0",
|
||||||
"dotenv-extended": "^2.2.0",
|
"dotenv-extended": "^2.3.0",
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.3",
|
||||||
"express-promise-router": "^3.0.3",
|
"express-promise-router": "^3.0.3",
|
||||||
"fs-extra": "^7.0.0",
|
"fs-extra": "^7.0.0",
|
||||||
"fs-walk": "^0.0.2",
|
"fs-walk": "^0.0.2",
|
||||||
"localize": "^0.4.7",
|
"localize": "^0.4.7",
|
||||||
"marked": "^0.5.0",
|
"marked": "^0.5.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"nexmo": "^2.3.2",
|
||||||
"pragmatismo-io-framework": "^1.0.15",
|
"pragmatismo-io-framework": "^1.0.15",
|
||||||
"reflect-metadata": "^0.1.12",
|
"reflect-metadata": "^0.1.12",
|
||||||
"request-promise-native": "^1.0.5",
|
"request-promise-native": "^1.0.5",
|
||||||
"sequelize": "^4.38.0",
|
"sequelize": "^4.38.1",
|
||||||
"sequelize-typescript": "^0.6.6",
|
"sequelize-typescript": "^0.6.6",
|
||||||
"sqlite3": "^4.0.2",
|
"sqlite3": "^4.0.2",
|
||||||
"swagger-client": "^3.8.19",
|
"swagger-client": "^3.8.21",
|
||||||
"tedious": "^2.6.4",
|
"tedious": "^2.6.4",
|
||||||
"url-join": "^4.0.0",
|
"url-join": "^4.0.0",
|
||||||
"wait-until": "^0.0.2",
|
"wait-until": "^0.0.2",
|
||||||
|
|
|
@ -83,7 +83,6 @@ export class GBServer {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
logger.info(`Accepting connections on ${port}...`)
|
logger.info(`Accepting connections on ${port}...`)
|
||||||
logger.info(`Starting instances...`)
|
|
||||||
|
|
||||||
// Reads basic configuration, initialize minimal services.
|
// Reads basic configuration, initialize minimal services.
|
||||||
|
|
||||||
|
@ -93,6 +92,7 @@ export class GBServer {
|
||||||
|
|
||||||
// Boot a bot package if any.
|
// Boot a bot package if any.
|
||||||
|
|
||||||
|
logger.info(`Starting instances...`)
|
||||||
let deployer = new GBDeployer(core, new GBImporter(core))
|
let deployer = new GBDeployer(core, new GBImporter(core))
|
||||||
|
|
||||||
// Build a minimal bot instance for each .gbot deployment.
|
// Build a minimal bot instance for each .gbot deployment.
|
||||||
|
|
Loading…
Add table
Reference in a new issue