new(core.gbapp): Param ENABLE_PARAMS_ONLINE added.

This commit is contained in:
Rodrigo Rodriguez 2020-08-22 18:41:54 -03:00
parent 8db05053d5
commit 56ef935676
5 changed files with 211 additions and 201 deletions

View file

@ -51,8 +51,6 @@ const { join } = require('path');
const shell = require('any-shell-escape'); const shell = require('any-shell-escape');
const { exec } = require('child_process'); const { exec } = require('child_process');
const prism = require('prism-media'); const prism = require('prism-media');
const sdk = require('microsoft-cognitiveservices-speech-sdk');
sdk.Recognizer.enableTelemetry(false);
const uuidv4 = require('uuid/v4'); const uuidv4 = require('uuid/v4');
const request = require('request-promise-native'); const request = require('request-promise-native');
const fs = require('fs'); const fs = require('fs');
@ -162,7 +160,9 @@ export class GBConversationalService {
const name = GBAdminService.getRndReadableIdentifier(); const name = GBAdminService.getRndReadableIdentifier();
const waveFilename = `work/tmp${name}.pcm`; const waveFilename = `work/tmp${name}.pcm`;
const sdk = require('microsoft-cognitiveservices-speech-sdk');
sdk.Recognizer.enableTelemetry(false);
var audioConfig = sdk.AudioConfig.fromAudioFileOutput(waveFilename); var audioConfig = sdk.AudioConfig.fromAudioFileOutput(waveFilename);
var speechConfig = sdk.SpeechConfig.fromSubscription(speechKey, cloudRegion); var speechConfig = sdk.SpeechConfig.fromSubscription(speechKey, cloudRegion);

View file

@ -56,7 +56,6 @@ import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp';
import { GBSharePointPackage } from '../../sharepoint.gblib'; import { GBSharePointPackage } from '../../sharepoint.gblib';
import { CollectionUtil } from 'pragmatismo-io-framework'; import { CollectionUtil } from 'pragmatismo-io-framework';
const opn = require('opn'); const opn = require('opn');
/** /**
@ -127,8 +126,8 @@ export class GBCoreService implements IGBCoreService {
const logging: boolean | Function = const logging: boolean | Function =
GBConfigService.get('STORAGE_LOGGING') === 'true' GBConfigService.get('STORAGE_LOGGING') === 'true'
? (str: string): void => { ? (str: string): void => {
GBLog.info(str); GBLog.info(str);
} }
: false; : false;
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true'; const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
@ -147,7 +146,8 @@ export class GBCoreService implements IGBCoreService {
options: { options: {
encrypt: encrypt encrypt: encrypt
} }
}, pool: { },
pool: {
max: 32, max: 32,
min: 8, min: 8,
idle: 40000, idle: 40000,
@ -156,12 +156,7 @@ export class GBCoreService implements IGBCoreService {
} }
}; };
this.sequelize = new Sequelize( this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
database,
username,
password,
sequelizeOptions
);
if (this.dialect === 'mssql') { if (this.dialect === 'mssql') {
this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator; this.queryGenerator = this.sequelize.getQueryInterface().QueryGenerator;
@ -211,7 +206,6 @@ export class GBCoreService implements IGBCoreService {
*/ */
public async loadInstances(): Promise<IGBInstance[]> { public async loadInstances(): Promise<IGBInstance[]> {
if (process.env.LOAD_ONLY !== undefined) { if (process.env.LOAD_ONLY !== undefined) {
const bots = process.env.LOAD_ONLY.split(`;`); const bots = process.env.LOAD_ONLY.split(`;`);
const and = []; const and = [];
await CollectionUtil.asyncForEach(bots, async e => { await CollectionUtil.asyncForEach(bots, async e => {
@ -224,8 +218,7 @@ export class GBCoreService implements IGBCoreService {
} }
}; };
return GuaribasInstance.findAll(options); return GuaribasInstance.findAll(options);
} } else {
else {
const options = { where: { state: 'active' } }; const options = { where: { state: 'active' } };
return GuaribasInstance.findAll(options); return GuaribasInstance.findAll(options);
} }
@ -243,7 +236,6 @@ export class GBCoreService implements IGBCoreService {
* Loads just one Bot instance. * Loads just one Bot instance.
*/ */
public async loadInstanceByActivationCode(code: string): Promise<IGBInstance> { public async loadInstanceByActivationCode(code: string): Promise<IGBInstance> {
let options = { where: { activationCode: code, state: 'active' } }; let options = { where: { activationCode: code, state: 'active' } };
return await GuaribasInstance.findOne(options); return await GuaribasInstance.findOne(options);
@ -283,8 +275,7 @@ STORAGE_SYNC=true
public async ensureProxy(port): Promise<string> { public async ensureProxy(port): Promise<string> {
try { try {
if (fs.existsSync('node_modules/ngrok/bin/ngrok.exe') || if (fs.existsSync('node_modules/ngrok/bin/ngrok.exe') || fs.existsSync('node_modules/ngrok/bin/ngrok')) {
fs.existsSync('node_modules/ngrok/bin/ngrok')) {
const ngrok = require('ngrok'); const ngrok = require('ngrok');
return await ngrok.connect({ port: port }, 10); return await ngrok.connect({ port: port }, 10);
@ -302,7 +293,6 @@ STORAGE_SYNC=true
} }
public installWebHook(isGet: boolean, url: string, callback: any) { public installWebHook(isGet: boolean, url: string, callback: any) {
if (isGet) { if (isGet) {
GBServer.globals.server.get(url, (req, res) => { GBServer.globals.server.get(url, (req, res) => {
callback(req, res); callback(req, res);
@ -311,7 +301,6 @@ STORAGE_SYNC=true
GBServer.globals.server.post(url, (req, res) => { GBServer.globals.server.post(url, (req, res) => {
callback(req, res); callback(req, res);
}); });
} }
} }
@ -323,7 +312,6 @@ STORAGE_SYNC=true
GBServer.globals.wwwroot = localPath; GBServer.globals.wwwroot = localPath;
} }
public async deleteInstance(botId: string) { public async deleteInstance(botId: string) {
const options = { where: {} }; const options = { where: {} };
options.where = { botId: botId }; options.where = { botId: botId };
@ -360,21 +348,19 @@ STORAGE_SYNC=true
let instances: IGBInstance[]; let instances: IGBInstance[];
try { try {
instances = await core.loadInstances(); instances = await core.loadInstances();
if (process.env.ENDPOINT_UPDATE === "true") { if (process.env.ENDPOINT_UPDATE === 'true') {
await CollectionUtil.asyncForEach(instances, async instance => { await CollectionUtil.asyncForEach(instances, async instance => {
GBLog.info(`Updating bot endpoint for ${instance.botId}...`); GBLog.info(`Updating bot endpoint for ${instance.botId}...`);
try { try {
await installationDeployer.updateBotProxy( await installationDeployer.updateBotProxy(
instance.botId, instance.botId,
GBConfigService.get("CLOUD_GROUP"), GBConfigService.get('CLOUD_GROUP'),
`${proxyAddress}/api/messages/${instance.botId}` `${proxyAddress}/api/messages/${instance.botId}`
); );
} catch (error) { } catch (error) {
if (error.code === "ResourceNotFound") { if (error.code === 'ResourceNotFound') {
GBLog.warn(`Bot ${instance.botId} not found on resource group ${GBConfigService.get("CLOUD_GROUP")}.`); GBLog.warn(`Bot ${instance.botId} not found on resource group ${GBConfigService.get('CLOUD_GROUP')}.`);
} } else {
else {
throw new Error(`Error updating bot proxy, details: ${error}.`); throw new Error(`Error updating bot proxy, details: ${error}.`);
} }
} }
@ -427,25 +413,27 @@ STORAGE_SYNC=true
// Loads all system packages. // Loads all system packages.
const sysPackages: IGBPackage[] = []; const sysPackages: IGBPackage[] = [];
await CollectionUtil.asyncForEach([ await CollectionUtil.asyncForEach(
GBAdminPackage, [
GBCorePackage, GBAdminPackage,
GBSecurityPackage, GBCorePackage,
GBKBPackage, GBSecurityPackage,
GBCustomerSatisfactionPackage, GBKBPackage,
GBAnalyticsPackage, GBCustomerSatisfactionPackage,
GBWhatsappPackage, GBAnalyticsPackage,
GBAzureDeployerPackage, GBWhatsappPackage,
GBSharePointPackage, GBAzureDeployerPackage,
], async e => { GBSharePointPackage
GBLog.info(`Loading sys package: ${e.name}...`); ],
async e => {
GBLog.info(`Loading sys package: ${e.name}...`);
const p = Object.create(e.prototype) as IGBPackage; const p = Object.create(e.prototype) as IGBPackage;
sysPackages.push(p); sysPackages.push(p);
await p.loadPackage(core, core.sequelize); await p.loadPackage(core, core.sequelize);
}
}); );
return sysPackages; return sysPackages;
} }
@ -515,28 +503,22 @@ STORAGE_SYNC=true
if (matches !== null) { if (matches !== null) {
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, (match: string, ...args: any[]): string => {
re2, return `CONSTRAINT [${table}_pk] ${match}`;
(match: string, ...args: any[]): string => { });
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, (match: string, ...args: any[]): string => {
re3, const fkcols = args[0];
(match: string, ...args: any[]): string => { let fkname = table;
const fkcols = args[0]; let matches2 = re4.exec(fkcols);
let fkname = table; while (matches2 !== null) {
let matches2 = re4.exec(fkcols); fkname += `_${matches2[1]}`;
while (matches2 !== null) { matches2 = re4.exec(fkcols);
fkname += `_${matches2[1]}`;
matches2 = re4.exec(fkcols);
}
return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
} }
);
return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
});
} }
return sql; return sql;
@ -558,20 +540,17 @@ STORAGE_SYNC=true
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, (match: string, ...args: any[]): string => {
re2, const fkcols = args[2];
(match: string, ...args: any[]): string => { let fkname = table;
const fkcols = args[2]; let matches2 = re3.exec(fkcols);
let fkname = table; while (matches2 !== null) {
let matches2 = re3.exec(fkcols); fkname += `_${matches2[1]}`;
while (matches2 !== null) { matches2 = re3.exec(fkcols);
fkname += `_${matches2[1]}`;
matches2 = re3.exec(fkcols);
}
return `${args[0] ? args[0] : ''}CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
} }
);
return `${args[0] ? args[0] : ''}CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
});
} }
return sql; return sql;
@ -591,7 +570,7 @@ STORAGE_SYNC=true
/** /**
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx * Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
* and loaded into the work folder from /publish command. * and loaded into the work folder from /publish command.
* *
* @param name Name of param to get from instance. * @param name Name of param to get from instance.
* @param defaultValue Value returned when no param is defined in Config.xlsx. * @param defaultValue Value returned when no param is defined in Config.xlsx.
*/ */
@ -601,19 +580,22 @@ STORAGE_SYNC=true
const params = JSON.parse(instance.params); const params = JSON.parse(instance.params);
value = params ? params[name] : defaultValue; value = params ? params[name] : defaultValue;
} }
if (typeof (defaultValue) === "boolean") { if (typeof defaultValue === 'boolean') {
return new Boolean(value ? value.toLowerCase() === "true" : defaultValue); return new Boolean(value ? value.toLowerCase() === 'true' : defaultValue);
} }
if (typeof (defaultValue) === "string") { if (typeof defaultValue === 'string') {
return value ? value : defaultValue; return value ? value : defaultValue;
} }
if (typeof (defaultValue) === "number") { if (typeof defaultValue === 'number') {
return new Number(value ? defaultValue : (defaultValue ? defaultValue : 0)); return new Number(value ? defaultValue : defaultValue ? defaultValue : 0);
} }
value = instance['dataValues'][name];
if (value === null) { if (instance['dataValues']) {
const minBoot = GBServer.globals.minBoot as any; value = instance['dataValues'][name];
value = minBoot.instance.datavalues[name]; if (value === null) {
const minBoot = GBServer.globals.minBoot as any;
value = minBoot.instance.datavalues[name];
}
} }
return value; return value;

View file

@ -374,7 +374,9 @@ export class GBDeployer implements IGBDeployer {
if (Fs.existsSync(localPath)) { if (Fs.existsSync(localPath)) {
await this.deployBotFromLocalPath(localPath, GBServer.globals.publicAddress); await this.deployBotFromLocalPath(localPath, GBServer.globals.publicAddress);
} }
min.instance.params = await this.loadParamsFromExcel(min); if (process.env.ENABLE_PARAMS_ONLINE === "true"){
min.instance.params = await this.loadParamsFromExcel(min);
}
await this.core.saveInstance(min.instance); await this.core.saveInstance(min.instance);
break; break;

View file

@ -112,14 +112,12 @@ export class GBMinService {
* *
*/ */
public async buildMin( public async buildMin(instances: IGBInstance[]) {
instances: IGBInstance[],
) {
// Serves default UI on root address '/' if web enabled. // Serves default UI on root address '/' if web enabled.
if (process.env.DISABLE_WEB !== 'true') { if (process.env.DISABLE_WEB !== 'true') {
let url = GBServer.globals.wwwroot ? let url = GBServer.globals.wwwroot
GBServer.globals.wwwroot : ? GBServer.globals.wwwroot
urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'); : urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build');
GBServer.globals.server.use('/', express.static(url)); GBServer.globals.server.use('/', express.static(url));
} }
@ -135,7 +133,6 @@ export class GBMinService {
const url = '/webhooks/whatsapp'; const url = '/webhooks/whatsapp';
GBServer.globals.server.post(url, async (req, res) => { GBServer.globals.server.post(url, async (req, res) => {
try { try {
const id = req.body.messages[0].chatId.split('@')[0]; const id = req.body.messages[0].chatId.split('@')[0];
const senderName = req.body.messages[0].senderName; const senderName = req.body.messages[0].senderName;
const text = req.body.messages[0].body; const text = req.body.messages[0].body;
@ -144,10 +141,14 @@ export class GBMinService {
return; // Exit here. return; // Exit here.
} }
let activeMin; let activeMin;
if (process.env.WHATSAPP_WELCOME_DISABLED !== "true") { if (process.env.WHATSAPP_WELCOME_DISABLED !== 'true') {
let toSwitchMin = GBServer.globals.minInstances.filter(p => p.instance.botId.toLowerCase() === text.toLowerCase())[0]; let toSwitchMin = GBServer.globals.minInstances.filter(
p => p.instance.botId.toLowerCase() === text.toLowerCase()
)[0];
if (!toSwitchMin) { if (!toSwitchMin) {
toSwitchMin = GBServer.globals.minInstances.filter(p => p.instance.activationCode ? p.instance.activationCode.toLowerCase() === text.toLowerCase() : false)[0]; toSwitchMin = GBServer.globals.minInstances.filter(p =>
p.instance.activationCode ? p.instance.activationCode.toLowerCase() === text.toLowerCase() : false
)[0];
} }
activeMin = toSwitchMin ? toSwitchMin : GBServer.globals.minBoot; activeMin = toSwitchMin ? toSwitchMin : GBServer.globals.minBoot;
@ -157,37 +158,42 @@ export class GBMinService {
let user = await sec.getUserFromSystemId(id); let user = await sec.getUserFromSystemId(id);
if (user === null) { if (user === null) {
user = await sec.ensureUser(activeMin.instance.instanceId, id, senderName, "", "whatsapp", senderName); user = await sec.ensureUser(activeMin.instance.instanceId, id, senderName, '', 'whatsapp', senderName);
await (activeMin as any).whatsAppDirectLine.sendToDevice(id, `Olá! Seja bem-vinda(o)!\nMe chamo ${activeMin.instance.title}. Como posso ajudar? Pode me falar que eu te ouço, me manda um aúdio.`); await (activeMin as any).whatsAppDirectLine.sendToDevice(
id,
`Olá! Seja bem-vinda(o)!\nMe chamo ${activeMin.instance.title}. Como posso ajudar? Pode me falar que eu te ouço, me manda um aúdio.`
);
res.end(); res.end();
} else { } else {
// User wants to switch bots. // User wants to switch bots.
if (toSwitchMin !== undefined) { if (toSwitchMin !== undefined) {
const instance = await this.core.loadInstanceByBotId(activeMin.botId); const instance = await this.core.loadInstanceByBotId(activeMin.botId);
await sec.updateUserInstance(id, instance.instanceId); await sec.updateUserInstance(id, instance.instanceId);
await (activeMin as any).whatsAppDirectLine.resetConversationId(id); await (activeMin as any).whatsAppDirectLine.resetConversationId(id);
await (activeMin as any).whatsAppDirectLine.sendToDevice(id, `Agora falando com ${activeMin.instance.title}...`); await (activeMin as any).whatsAppDirectLine.sendToDevice(
id,
`Agora falando com ${activeMin.instance.title}...`
);
res.end(); res.end();
} } else {
else {
activeMin = GBServer.globals.minInstances.filter(p => p.instance.instanceId === user.instanceId)[0]; activeMin = GBServer.globals.minInstances.filter(p => p.instance.instanceId === user.instanceId)[0];
if (activeMin === undefined) { if (activeMin === undefined) {
activeMin = GBServer.globals.minBoot; activeMin = GBServer.globals.minBoot;
await (activeMin as any).whatsAppDirectLine.sendToDevice(id, `O outro Bot que você estava falando(${user.instanceId}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...`); await (activeMin as any).whatsAppDirectLine.sendToDevice(
id,
`O outro Bot que você estava falando(${user.instanceId}), não está mais disponível. Agora você está falando comigo, ${activeMin.instance.title}...`
);
} }
await (activeMin as any).whatsAppDirectLine.received(req, res); await (activeMin as any).whatsAppDirectLine.received(req, res);
} }
} }
} } else {
else {
await (GBServer.globals.minBoot as any).whatsAppDirectLine.received(req, res); await (GBServer.globals.minBoot as any).whatsAppDirectLine.received(req, res);
} }
} catch (error) { } catch (error) {
GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error}`); GBLog.error(`Error on Whatsapp callback: ${error.data ? error.data : error}`);
} }
}); });
await CollectionUtil.asyncForEach(instances, async instance => { await CollectionUtil.asyncForEach(instances, async instance => {
@ -210,9 +216,12 @@ export class GBMinService {
} }
public async mountBot(instance: IGBInstance) { public async mountBot(instance: IGBInstance) {
// Build bot adapter. // Build bot adapter.
const { min, adapter, conversationState } = await this.buildBotAdapter(instance, GBServer.globals.sysPackages, GBServer.globals.appPackages); const { min, adapter, conversationState } = await this.buildBotAdapter(
instance,
GBServer.globals.sysPackages,
GBServer.globals.appPackages
);
GBServer.globals.minInstances.push(min); GBServer.globals.minInstances.push(min);
await this.deployer.deployPackage(min, 'packages/default.gbtheme'); await this.deployer.deployPackage(min, 'packages/default.gbtheme');
@ -250,8 +259,14 @@ export class GBMinService {
if (process.env.DISABLE_WEB !== 'true') { if (process.env.DISABLE_WEB !== 'true') {
const uiUrl = `/${instance.botId}`; const uiUrl = `/${instance.botId}`;
const uiUrlAlt = `/${instance.activationCode}`; const uiUrlAlt = `/${instance.activationCode}`;
GBServer.globals.server.use(uiUrl, express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'))); GBServer.globals.server.use(
GBServer.globals.server.use(uiUrlAlt, express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'))); uiUrl,
express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'))
);
GBServer.globals.server.use(
uiUrlAlt,
express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'))
);
GBLog.info(`Bot UI ${GBMinService.uiPackage} accessible at: ${uiUrl} and ${uiUrlAlt}.`); GBLog.info(`Bot UI ${GBMinService.uiPackage} accessible at: ${uiUrl} and ${uiUrlAlt}.`);
} }
@ -273,7 +288,7 @@ export class GBMinService {
server.get(`/${min.instance.botId}/check`, async (req, res) => { server.get(`/${min.instance.botId}/check`, async (req, res) => {
try { try {
if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) { if (min.whatsAppDirectLine != undefined && instance.whatsappServiceKey !== null) {
if (!await min.whatsAppDirectLine.check(min)) { if (!(await min.whatsAppDirectLine.check(min))) {
const error = `WhatsApp API lost connection.`; const error = `WhatsApp API lost connection.`;
GBLog.error(error); GBLog.error(error);
res.status(500).send(error); res.status(500).send(error);
@ -289,7 +304,6 @@ export class GBMinService {
}); });
} }
private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) { private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) {
server.get(`/${min.instance.botId}/token`, async (req, res) => { server.get(`/${min.instance.botId}/token`, async (req, res) => {
const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState'); const state = await min.adminService.getValue(instance.instanceId, 'AntiCSRFAttackState');
@ -334,7 +348,7 @@ export class GBMinService {
); );
authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${ authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${
min.instance.marketplaceId min.instance.marketplaceId
}&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`; }&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`;
res.redirect(authorizationUrl); res.redirect(authorizationUrl);
}); });
} }
@ -399,9 +413,7 @@ export class GBMinService {
return JSON.parse(json); return JSON.parse(json);
} catch (error) { } catch (error) {
const msg = `[botId:${ const msg = `[botId:${instance.botId}] Error calling Direct Line client, verify Bot endpoint on the cloud. Error is: ${error}.`;
instance.botId
}] 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));
} }
@ -414,7 +426,6 @@ export class GBMinService {
* *
*/ */
private async getSTSToken(instance: any) { private async getSTSToken(instance: any) {
const options = { const options = {
url: instance.speechEndpoint, url: instance.speechEndpoint,
method: 'POST', method: 'POST',
@ -443,8 +454,10 @@ export class GBMinService {
const userState = new UserState(storage); const userState = new UserState(storage);
adapter.use(new AutoSaveStateMiddleware(conversationState, userState)); adapter.use(new AutoSaveStateMiddleware(conversationState, userState));
MicrosoftAppCredentials.trustServiceUrl('https://directline.botframework.com', MicrosoftAppCredentials.trustServiceUrl(
new Date(new Date().setFullYear(new Date().getFullYear() + 10))); 'https://directline.botframework.com',
new Date(new Date().setFullYear(new Date().getFullYear() + 10))
);
// The minimal bot is built here. // The minimal bot is built here.
@ -474,12 +487,11 @@ export class GBMinService {
let handled = false; let handled = false;
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => { await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
let services: ConcatArray<never>; let services: ConcatArray<never>;
if (services = await e.onExchangeData(min, "getServices", null)) { if ((services = await e.onExchangeData(min, 'getServices', null))) {
min.gbappServices.concat(services); min.gbappServices.concat(services);
} }
}); });
if (min.instance.whatsappServiceKey !== null) { if (min.instance.whatsappServiceKey !== null) {
min.whatsAppDirectLine = new WhatsappDirectLine( min.whatsAppDirectLine = new WhatsappDirectLine(
min, min,
@ -490,20 +502,17 @@ export class GBMinService {
min.instance.whatsappServiceUrl min.instance.whatsappServiceUrl
); );
await min.whatsAppDirectLine.setup(true); await min.whatsAppDirectLine.setup(true);
} } else {
else {
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
if (minBoot.instance.whatsappServiceKey) { if (minBoot.instance.whatsappServiceKey) {
min.whatsAppDirectLine = new WhatsappDirectLine(
min.whatsAppDirectLine = min,
new WhatsappDirectLine( min.botId,
min, min.instance.whatsappBotKey,
min.botId, minBoot.instance.whatsappServiceKey,
min.instance.whatsappBotKey, minBoot.instance.whatsappServiceNumber,
minBoot.instance.whatsappServiceKey, minBoot.instance.whatsappServiceUrl
minBoot.instance.whatsappServiceNumber, );
minBoot.instance.whatsappServiceUrl
);
await min.whatsAppDirectLine.setup(false); await min.whatsAppDirectLine.setup(false);
} }
} }
@ -545,7 +554,6 @@ export class GBMinService {
} }
} }
}); });
} }
/** /**
@ -566,7 +574,6 @@ export class GBMinService {
step.context.activity.locale = 'pt-BR'; step.context.activity.locale = 'pt-BR';
try { try {
const user = await min.userProfile.get(context, {}); const user = await min.userProfile.get(context, {});
// First time processing. // First time processing.
@ -586,8 +593,14 @@ export class GBMinService {
let sec = new SecService(); let sec = new SecService();
const member = context.activity.from; const member = context.activity.from;
const persistedUser = await sec.ensureUser(instance.instanceId, member.id, const persistedUser = await sec.ensureUser(
member.name, "", "web", member.name); instance.instanceId,
member.id,
member.name,
'',
'web',
member.name
);
const analytics = new AnalyticsService(); const analytics = new AnalyticsService();
@ -596,7 +609,6 @@ export class GBMinService {
} }
await min.userProfile.set(step.context, user); await min.userProfile.set(step.context, user);
} }
GBLog.info( GBLog.info(
@ -630,7 +642,11 @@ export class GBMinService {
const msg = `ERROR: ${error.message} ${error.stack ? error.stack : ''}`; const msg = `ERROR: ${error.message} ${error.stack ? error.stack : ''}`;
GBLog.error(msg); GBLog.error(msg);
await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].very_sorry_about_error); await min.conversationalService.sendText(
min,
step,
Messages[step.context.activity.locale].very_sorry_about_error
);
await step.beginDialog('/ask', { isReturning: true }); await step.beginDialog('/ask', { isReturning: true });
} }
}); });
@ -665,19 +681,20 @@ export class GBMinService {
} }
private async processMessageActivity(context, min: GBMinInstance, step: GBDialogStep) { private async processMessageActivity(context, min: GBMinInstance, step: GBDialogStep) {
let message: GuaribasConversationMessage; let message: GuaribasConversationMessage;
if (process.env.PRIVACY_STORE_MESSAGES === "true") { if (process.env.PRIVACY_STORE_MESSAGES === 'true') {
// Adds message to the analytics layer. // Adds message to the analytics layer.
const analytics = new AnalyticsService(); const analytics = new AnalyticsService();
const user = await min.userProfile.get(context, {}); const user = await min.userProfile.get(context, {});
if (user) { if (user) {
message = await analytics.createMessage(min.instance.instanceId, message = await analytics.createMessage(
user.conversation, user.systemUser.userId, min.instance.instanceId,
context.activity.text); user.conversation,
user.systemUser.userId,
context.activity.text
);
} }
} }
@ -685,14 +702,13 @@ export class GBMinService {
const globalQuit = (locale, utterance) => { const globalQuit = (locale, utterance) => {
return utterance.match(Messages.global_quit); return utterance.match(Messages.global_quit);
} };
const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined; const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined;
const simpleLocale = context.activity.locale.substring(0, 2); const simpleLocale = context.activity.locale.substring(0, 2);
const hasBadWord = wash.check(simpleLocale, context.activity.text); const hasBadWord = wash.check(simpleLocale, context.activity.text);
if (hasBadWord) { if (hasBadWord) {
await step.beginDialog('/pleaseNoBadWords'); await step.beginDialog('/pleaseNoBadWords');
} else if (isVMCall) { } else if (isVMCall) {
@ -704,8 +720,8 @@ export class GBMinService {
parts.splice(0, 1); parts.splice(0, 1);
let args = parts.join(' '); let args = parts.join(' ');
await step.beginDialog(dialogName, { args: args }); await step.beginDialog(dialogName, { args: args });
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
} else if (globalQuit(step.context.activity.locale, context.activity.text)) { // TODO: Hard-code additional languages. // TODO: Hard-code additional languages.
await step.cancelAllDialogs(); await step.cancelAllDialogs();
await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].canceled); await min.conversationalService.sendText(min, step, Messages[step.context.activity.locale].canceled);
} else if (context.activity.text === 'admin') { } else if (context.activity.text === 'admin') {
@ -716,61 +732,71 @@ export class GBMinService {
await step.beginDialog('/menu', JSON.parse(context.activity.text)); await step.beginDialog('/menu', 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 {
if (!await this.deployer.getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`)) { if (!(await this.deployer.getStoragePackageByName(min.instance.instanceId, `${min.instance.botId}.gbkb`))) {
await step.context.sendActivity(`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`); await step.context.sendActivity(
`Oi, ainda não possuo pacotes de conhecimento publicados. Por favor, aguarde alguns segundos enquanto eu auto-publico alguns pacotes.`
);
return await step.beginDialog('/publish', { confirm: true }); return await step.beginDialog('/publish', { confirm: true });
} }
if (step.activeDialog !== undefined) { if (step.activeDialog !== undefined) {
await step.continueDialog(); await step.continueDialog();
} else { } else {
let query = context.activity.text; let query = context.activity.text;
let locale = 'pt'; let locale = 'pt';
if (process.env.TRANSLATOR_DISABLED !== "true" || if (
min.core.getParam<boolean>(min.instance, 'Enable Worldwide Translator')) { process.env.TRANSLATOR_DISABLED !== 'true' ||
min.core.getParam<boolean>(min.instance, 'Enable Worldwide Translator')
) {
const minBoot = GBServer.globals.minBoot as any; // TODO: Switch keys automatically to master/per bot. const minBoot = GBServer.globals.minBoot as any; // TODO: Switch keys automatically to master/per bot.
locale = await AzureText.getLocale(minBoot.instance.textAnalyticsKey ? locale = await AzureText.getLocale(
minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey, minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
minBoot.instance.textAnalyticsEndpoint ? minBoot.instance.textAnalyticsEndpoint
minBoot.instance.textAnalyticsEndpoint : minBoot.instance.textAnalyticsEndpoint, query); ? minBoot.instance.textAnalyticsEndpoint
: minBoot.instance.textAnalyticsEndpoint,
query
);
} }
let sec = new SecService(); let sec = new SecService();
const member = step.context.activity.from; const member = step.context.activity.from;
const user = await sec.ensureUser(min.instance.instanceId, member.id, const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
member.name, "", "web", member.name);
user.locale = locale; user.locale = locale;
await user.save(); await user.save();
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
const notTranslatedQuery = query; const notTranslatedQuery = query;
query = await min.conversationalService.translate(min, query = await min.conversationalService.translate(
min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
query, query,
'pt'); 'pt'
);
GBLog.info(`Translated text: ${query}.`); GBLog.info(`Translated text: ${query}.`);
// Checks if any .gbapp will handle this answer, if not goes to kb.gbapp. // Checks if any .gbapp will handle this answer, if not goes to kb.gbapp.
let handled = false; let handled = false;
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => { await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
if (await e.onExchangeData(min, "handleAnswer", { if (
query: query, step: step, await e.onExchangeData(min, 'handleAnswer', {
notTranslatedQuery: notTranslatedQuery, query: query,
message: message['dataValues'], step: step,
user: user['dataValues'] notTranslatedQuery: notTranslatedQuery,
})) { message: message ? message['dataValues'] : null,
user: user ? user['dataValues'] : null
})
) {
handled = true; handled = true;
} }
}); });
if (!handled) { if (!handled) {
await step.beginDialog('/answer', { await step.beginDialog('/answer', {
query: query, message: message query: query,
message: message
}); });
} }
} }

View file

@ -103,45 +103,52 @@ export class AskDialog extends IGBDialog {
const translatorEnabled = () => { const translatorEnabled = () => {
if (min.instance.params) { if (min.instance.params) {
const params = JSON.parse(min.instance.params); const params = JSON.parse(min.instance.params);
return params ? params['Enable Worldwide Translator'] === "TRUE" : false; return params ? params['Enable Worldwide Translator'] === 'TRUE' : false;
} }
return false; return false;
} // TODO: Encapsulate. }; // TODO: Encapsulate.
let query = step.result; let query = step.result;
let locale = 'pt'; let locale = 'pt';
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
if (process.env.TRANSLATOR_DISABLED !== "true" && translatorEnabled()) { if (process.env.TRANSLATOR_DISABLED !== 'true' && translatorEnabled()) {
locale = await AzureText.getLocale(minBoot.instance.textAnalyticsKey ? locale = await AzureText.getLocale(
minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey, minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
minBoot.instance.textAnalyticsEndpoint ? minBoot.instance.textAnalyticsEndpoint
minBoot.instance.textAnalyticsEndpoint : minBoot.instance.textAnalyticsEndpoint, query); ? minBoot.instance.textAnalyticsEndpoint
: minBoot.instance.textAnalyticsEndpoint,
query
);
} }
let sec = new SecService(); let sec = new SecService();
const member = step.context.activity.from; const member = step.context.activity.from;
const user = await sec.ensureUser(min.instance.instanceId, member.id, const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
member.name, "", "web", member.name);
user.locale = locale; user.locale = locale;
await user.save(); await user.save();
const notTranslatedQuery = query; const notTranslatedQuery = query;
query = await min.conversationalService.translate(min, query = await min.conversationalService.translate(
min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
query, query,
'pt'); 'pt'
GBLog.info(`Translated text: ${query}.`) );
GBLog.info(`Translated text: ${query}.`);
let handled = false; let handled = false;
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => { await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
if (await e.onExchangeData(min, "handleAnswer", { if (
query: query, step: step, await e.onExchangeData(min, 'handleAnswer', {
notTranslatedQuery: notTranslatedQuery, query: query,
message: query, step: step,
user: user['dataValues'] notTranslatedQuery: notTranslatedQuery,
})) { message: query,
user: user ? user['dataValues'] : null
})
) {
handled = true; handled = true;
} }
}); });
@ -153,8 +160,6 @@ export class AskDialog extends IGBDialog {
} else { } else {
return await step.next(); return await step.next();
} }
} else { } else {
return await step.next(); return await step.next();
} }
@ -170,10 +175,10 @@ export class AskDialog extends IGBDialog {
let sec = new SecService(); let sec = new SecService();
const member = step.context.activity.from; const member = step.context.activity.from;
const userDb = await sec.ensureUser(min.instance.instanceId, member.id, const userDb = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
member.name, "", "web", member.name);
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
text = await min.conversationalService.translate(min, text = await min.conversationalService.translate(
min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
text, text,
@ -218,7 +223,6 @@ export class AskDialog extends IGBDialog {
// Sends the answer to all outputs, including projector. // Sends the answer to all outputs, including projector.
return await AskDialog.handleAnswer(service, min, step, resultsA.answer); return await AskDialog.handleAnswer(service, min, step, resultsA.answer);
} else { } else {
// Second time running Search, now with no filter. // Second time running Search, now with no filter.
const resultsB = await service.ask(min.instance, text, searchScore, undefined); const resultsB = await service.ask(min.instance, text, searchScore, undefined);
@ -237,7 +241,6 @@ export class AskDialog extends IGBDialog {
} }
if (resultsB.answer) if (resultsB.answer)
// Sends the answer to all outputs, including projector. // Sends the answer to all outputs, including projector.
return await AskDialog.handleAnswer(service, min, step, resultsA.answer); return await AskDialog.handleAnswer(service, min, step, resultsA.answer);
@ -254,16 +257,13 @@ export class AskDialog extends IGBDialog {
} }
private static async handleAnswer(service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) { private static async handleAnswer(service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
if (answer.content.endsWith('.docx')) { if (answer.content.endsWith('.docx')) {
const mainName = answer.content.replace(/\s|\-/gi, '').split('.')[0]; const mainName = answer.content.replace(/\s|\-/gi, '').split('.')[0];
return await GBMinService.callVM(mainName, min, step); return await GBMinService.callVM(mainName, min, step);
} else { } else {
await service.sendAnswer(min, AskDialog.getChannel(step), step, answer); await service.sendAnswer(min, AskDialog.getChannel(step), step, answer);
return await step.replaceDialog('/ask', { isReturning: true }); return await step.replaceDialog('/ask', { isReturning: true });
} }
} }
private static getChannel(step): string { private static getChannel(step): string {