fix(core.gbapp): Language features optmized.
This commit is contained in:
parent
f925eedeea
commit
933729ae4d
11 changed files with 276 additions and 223 deletions
53
package-lock.json
generated
53
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "botserver",
|
||||
"version": "2.0.12",
|
||||
"version": "2.0.42",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -57,9 +57,9 @@
|
|||
}
|
||||
},
|
||||
"@azure/cosmos": {
|
||||
"version": "3.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.9.2.tgz",
|
||||
"integrity": "sha512-nS02/LyjE22osouSJGWw6DqJ34tbkEgAcysrbKyDzyiqdDKNprP8sAU43WGVr6Jxjw8jGBzg6rkHz9A+IvPcdg==",
|
||||
"version": "3.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.9.3.tgz",
|
||||
"integrity": "sha512-1mh8a6LAIykz24tJvQpafXiABUfq+HSAZBFJVZXea0Rd0qG8Ia9z8AK9FtPbC1nPvDC2RID2mRIjJvYbxRM/BA==",
|
||||
"requires": {
|
||||
"@types/debug": "^4.1.4",
|
||||
"debug": "^4.1.1",
|
||||
|
@ -71,7 +71,7 @@
|
|||
"semaphore": "^1.0.5",
|
||||
"tslib": "^2.0.0",
|
||||
"universal-user-agent": "^6.0.0",
|
||||
"uuid": "^8.1.0"
|
||||
"uuid": "^8.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
|
@ -2526,9 +2526,9 @@
|
|||
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ=="
|
||||
},
|
||||
"@types/documentdb": {
|
||||
"version": "1.10.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.7.tgz",
|
||||
"integrity": "sha512-IOob9vJEzPqKzSQdgcUrmKBZNx9ngwAB8fldI4B92/mPh3wHgTjRDW7CJDF9yDMOwvr9fM3+hq/d8I4RmbWCYQ==",
|
||||
"version": "1.10.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.8.tgz",
|
||||
"integrity": "sha512-GkOXovVMlMVTYkPomq9rOI79DmVOMZ0TDziL3H3TSlhUSm1/txi5qA49H/qZRDFsExagjnf5Cd/4xF8mXVxubw==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
|
@ -4484,9 +4484,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.17.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.40.tgz",
|
||||
"integrity": "sha512-3hZT2z2/531A5pc8hYhn1gU5Qb1SIRSgMLQ6zuHA5xtt16lWAxUGprtr8lJuc9zNJMXEIIBWfSnzqBP/4mglpA=="
|
||||
"version": "10.17.44",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.44.tgz",
|
||||
"integrity": "sha512-vHPAyBX1ffLcy4fQHmDyIUMUb42gHZjPHU66nhvbMzAWJqHnySGZ6STwN3rwrnSd1FHB0DI/RWgGELgKSYRDmw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -4608,9 +4608,9 @@
|
|||
}
|
||||
},
|
||||
"botlib": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/botlib/-/botlib-1.6.5.tgz",
|
||||
"integrity": "sha512-0K+BNnHGwryID0MCG8s3s9CVGzjyBLph7ngtZp1oBNwvfcMinGGiOtbcV3CRHdiOypPr/FFuKyqe+kBVTbOtlQ==",
|
||||
"version": "1.6.7",
|
||||
"resolved": "https://registry.npmjs.org/botlib/-/botlib-1.6.7.tgz",
|
||||
"integrity": "sha512-KE2WnfqMciWGGZpYcsIrjgwqnZriNhbj5kxwtsrQJbsfmSr4SToPWcP0wPlSuaa2DubtnpYcEjSzmydHH7Ag0A==",
|
||||
"requires": {
|
||||
"async": "3.1.0",
|
||||
"botbuilder": "4.7.0",
|
||||
|
@ -8562,9 +8562,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"is-buffer": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
|
||||
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
|
||||
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -12527,6 +12527,15 @@
|
|||
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-1.1.0.tgz",
|
||||
"integrity": "sha512-dEYmUqjtbivotqjraOe8UvhT/poFfog1BQRNsZm/MSEDDESk2cQ1tvD8kGyuN07TM/zoW+n42odL8zTeJupYdQ=="
|
||||
},
|
||||
"node-cron": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-2.0.3.tgz",
|
||||
"integrity": "sha512-eJI+QitXlwcgiZwNNSRbqsjeZMp5shyajMR81RZCqeW0ZDEj4zU9tpd4nTh/1JsBiKbF8d08FCewiipDmVIYjg==",
|
||||
"requires": {
|
||||
"opencollective-postinstall": "^2.0.0",
|
||||
"tz-offset": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node-emoji": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz",
|
||||
|
@ -16242,6 +16251,11 @@
|
|||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"opencollective-postinstall": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
|
||||
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="
|
||||
},
|
||||
"opn": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz",
|
||||
|
@ -21082,6 +21096,11 @@
|
|||
"function.name": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"tz-offset": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tz-offset/-/tz-offset-0.0.1.tgz",
|
||||
"integrity": "sha512-kMBmblijHJXyOpKzgDhKx9INYU4u4E1RPMB0HqmKSgWG8vEcf3exEfLh4FFfzd3xdQOw9EuIy/cP0akY6rHopQ=="
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.0.tgz",
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
"botbuilder-ai": "4.7.0",
|
||||
"botbuilder-dialogs": "4.7.0",
|
||||
"botframework-connector": "4.7.0",
|
||||
"botlib": "1.6.5",
|
||||
"botlib": "1.6.7",
|
||||
"cli-spinner": "0.2.10",
|
||||
"core-js": "^3.6.5",
|
||||
"dotenv-extended": "2.8.0",
|
||||
|
|
77
packages/core.gbapp/dialogs/LanguageDialog.ts
Normal file
77
packages/core.gbapp/dialogs/LanguageDialog.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*****************************************************************************\
|
||||
| ( )_ _ |
|
||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
|
||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
||||
| | | ( )_) | |
|
||||
| (_) \___/' |
|
||||
| |
|
||||
| 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. |
|
||||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @fileoverview General Bots server core.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { BotAdapter } from 'botbuilder';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { Messages } from '../strings';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { GBConversationalService } from '../services/GBConversationalService';
|
||||
/**
|
||||
* Dialog for the bot explains about itself.
|
||||
*/
|
||||
export class LanguageDialog extends IGBDialog {
|
||||
/**
|
||||
* Setup dialogs flows and define services call.
|
||||
*
|
||||
* @param bot The bot adapter.
|
||||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
public static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
min.dialogs.add(new WaterfallDialog('/language', [
|
||||
|
||||
async step => {
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
return await min.conversationalService.prompt (min, step,
|
||||
Messages[locale].which_language);
|
||||
},
|
||||
async step => {
|
||||
let sec = new SecService();
|
||||
let from = step.context.activity.from.id;
|
||||
const botId = step.result;
|
||||
const instance = await min.core.loadInstanceByBotId(botId);
|
||||
await sec.updateUserInstance(from, instance.instanceId);
|
||||
await min.conversationalService.sendText(min, step, `Opa, vamos lá!`);
|
||||
|
||||
return await step.next();
|
||||
}
|
||||
]));
|
||||
}
|
||||
}
|
|
@ -134,11 +134,26 @@ export class GBConfigService {
|
|||
value = undefined;
|
||||
break;
|
||||
case 'DISABLE_WEB':
|
||||
value = "false";
|
||||
value = 'false';
|
||||
break;
|
||||
case 'STORAGE_ACQUIRE_TIMEOUT':
|
||||
value = 40000;
|
||||
break;
|
||||
case 'LOCALE':
|
||||
value = 'en';
|
||||
break;
|
||||
case 'LANGUAGE_DETECTOR':
|
||||
value = false;
|
||||
break;
|
||||
case 'DEFAULT_USER_LANGUAGE':
|
||||
value = 'en';
|
||||
break;
|
||||
case 'DEFAULT_CONTENT_LANGUAGE':
|
||||
value = 'en';
|
||||
break;
|
||||
case 'ENABLE_SPELLING_CHECKER':
|
||||
value = false;
|
||||
break;
|
||||
default:
|
||||
GBLog.warn(`Invalid key on .env file: '${key}'`);
|
||||
break;
|
||||
|
|
|
@ -44,12 +44,12 @@ import { Readable } from 'stream';
|
|||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsService';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { WaterfallStep, WaterfallStepContext } from 'botbuilder-dialogs';
|
||||
import { MicrosoftAppCredentials } from 'botframework-connector';
|
||||
import { GBConfigService } from './GBConfigService';
|
||||
const urlJoin = require('url-join');
|
||||
const PasswordGenerator = require('strict-password-generator').default;
|
||||
const Nexmo = require('nexmo');
|
||||
import { CollectionUtil, AzureText } from 'pragmatismo-io-framework';
|
||||
const { join } = require('path');
|
||||
const shell = require('any-shell-escape');
|
||||
const { exec } = require('child_process');
|
||||
|
@ -477,7 +477,7 @@ export class GBConversationalService {
|
|||
|
||||
let nlp: RecognizerResult;
|
||||
try {
|
||||
const saved = step.context.activity.text
|
||||
const saved = step.context.activity.text;
|
||||
step.context.activity.text = text;
|
||||
nlp = await model.recognize(step.context);
|
||||
step.context.activity.text = saved;
|
||||
|
@ -516,7 +516,9 @@ export class GBConversationalService {
|
|||
return false;
|
||||
}
|
||||
|
||||
GBLog.info(`NLP called: ${intent}, entities: ${nlp.entities.length}, score: ${score} > required (nlpScore): ${min.instance.nlpScore}`);
|
||||
GBLog.info(
|
||||
`NLP called: ${intent}, entities: ${nlp.entities.length}, score: ${score} > required (nlpScore): ${min.instance.nlpScore}`
|
||||
);
|
||||
|
||||
try {
|
||||
step.activeDialog.state.options.entities = nlp.entities;
|
||||
|
@ -533,14 +535,39 @@ export class GBConversationalService {
|
|||
return false;
|
||||
}
|
||||
|
||||
async translate(min: GBMinInstance, key: string, endPoint: string, text: string, language: string): Promise<string> {
|
||||
public async getLanguage(min: GBMinInstance, text: string): Promise<string> {
|
||||
return await AzureText.getLocale(
|
||||
min.instance.textAnalyticsKey ? min.instance.textAnalyticsKey : min.instance.textAnalyticsKey,
|
||||
min.instance.textAnalyticsEndpoint ? min.instance.textAnalyticsEndpoint :
|
||||
min.instance.textAnalyticsEndpoint,
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
public async spellCheck(min: GBMinInstance, text: string): Promise<string> {
|
||||
const key = min.instance.spellcheckerKey ? min.instance.spellcheckerKey : min.instance.spellcheckerKey;
|
||||
if (key) {
|
||||
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||
const data = await AzureText.getSpelledText(min.instance.spellcheckerKey, text);
|
||||
if (data !== text) {
|
||||
GBLog.info(`Spelling corrected (processMessageActivity): ${data}`);
|
||||
text = data;
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public async translate(min: GBMinInstance, text: string, language: string): Promise<string> {
|
||||
const translatorEnabled = () => {
|
||||
if (min.instance.params) {
|
||||
const params = JSON.parse(min.instance.params);
|
||||
return params ? params['Enable Worldwide Translator'] === 'TRUE' : false;
|
||||
}
|
||||
return false;
|
||||
}; // TODO: Encapsulate.
|
||||
};
|
||||
const endPoint = min.instance.translatorEndpoint;
|
||||
const key = min.instance.translatorKey;
|
||||
|
||||
if (endPoint === null || !translatorEnabled() || process.env.TRANSLATOR_DISABLED === 'true') {
|
||||
return text;
|
||||
|
@ -585,41 +612,34 @@ export class GBConversationalService {
|
|||
}
|
||||
|
||||
public async prompt(min: GBMinInstance, step: GBDialogStep, text: string) {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
if (text !== null) {
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
text,
|
||||
user.locale ? user.locale : 'en'
|
||||
user.locale ? user.locale : min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
GBLog.info(`Translated text(4): ${text}.`);
|
||||
GBLog.info(`Translated text(prompt): ${text}.`);
|
||||
}
|
||||
|
||||
return await step.prompt('textPrompt', text ? text : {});
|
||||
}
|
||||
|
||||
public async sendText(min, step, text) {
|
||||
public async sendText(min: GBMinInstance, step, text) {
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
|
||||
if (user) {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
text,
|
||||
user.locale ? user.locale : 'en'
|
||||
user.locale ? user.locale : min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
GBLog.info(`Translated text(5): ${text}.`);
|
||||
|
||||
GBLog.info(`Translated text(sendText): ${text}.`);
|
||||
|
||||
const analytics = new AnalyticsService();
|
||||
const userProfile = await min.userProfile.get(step.context, {});
|
||||
analytics.createMessage(min.instance.instanceId, userProfile.conversation, null, text);
|
||||
|
|
|
@ -76,8 +76,6 @@ import { AnalyticsService } from '../../analytics.gblib/services/AnalyticsServic
|
|||
import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine';
|
||||
import fs = require('fs');
|
||||
import { GuaribasConversationMessage } from '../../analytics.gblib/models';
|
||||
import { GBCoreService } from './GBCoreService';
|
||||
import { DialogClass } from './GBAPIService';
|
||||
import { GBVMService } from './GBVMService';
|
||||
|
||||
/**
|
||||
|
@ -163,7 +161,6 @@ export class GBMinService {
|
|||
activeMin = toSwitchMin ? toSwitchMin : GBServer.globals.minBoot;
|
||||
|
||||
let sec = new SecService();
|
||||
|
||||
let user = await sec.getUserFromSystemId(id);
|
||||
|
||||
if (user === null) {
|
||||
|
@ -705,13 +702,13 @@ export class GBMinService {
|
|||
}
|
||||
|
||||
private async processMessageActivity(context, min: GBMinInstance, step: GBDialogStep) {
|
||||
let message: GuaribasConversationMessage;
|
||||
const user = await min.userProfile.get(context, {});
|
||||
|
||||
let message: GuaribasConversationMessage;
|
||||
if (process.env.PRIVACY_STORE_MESSAGES === 'true') {
|
||||
const analytics = new AnalyticsService();
|
||||
// Adds message to the analytics layer.
|
||||
|
||||
const analytics = new AnalyticsService();
|
||||
const user = await min.userProfile.get(context, {});
|
||||
if (user) {
|
||||
message = await analytics.createMessage(
|
||||
min.instance.instanceId,
|
||||
|
@ -744,10 +741,9 @@ export class GBMinService {
|
|||
parts.splice(0, 1);
|
||||
let args = parts.join(' ');
|
||||
|
||||
if (cmdOrDialogName === '/call'){
|
||||
if (cmdOrDialogName === '/call') {
|
||||
await GBVMService.callVM(args, min, step, this.deployer);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
await step.beginDialog(cmdOrDialogName, { args: args });
|
||||
}
|
||||
} else if (globalQuit(step.context.activity.locale, context.activity.text)) {
|
||||
|
@ -767,57 +763,48 @@ export class GBMinService {
|
|||
);
|
||||
await step.beginDialog('/publish', { confirm: true, firstTime: true });
|
||||
} else {
|
||||
let text = context.activity.text;
|
||||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/gi, '');
|
||||
|
||||
// Spells check the input text before translating.
|
||||
|
||||
text = await min.conversationalService.spellCheck(min, text);
|
||||
|
||||
// Detects user typed language and updates their locale profile if applies.
|
||||
|
||||
let locale = min.core.getParam<string>(
|
||||
min.instance,
|
||||
'Default User Language',
|
||||
GBConfigService.get('DEFAULT_USER_LANGUAGE')
|
||||
);
|
||||
let detectLanguage = min.core.getParam<boolean>(
|
||||
min.instance,
|
||||
'Language Detector',
|
||||
GBConfigService.get('LANGUAGE_DETECTOR') as any
|
||||
);
|
||||
if (detectLanguage) {
|
||||
locale = await min.conversationalService.getLanguage(min, text);
|
||||
const systemUser = user.systemUser;
|
||||
if (systemUser.locale != locale) {
|
||||
let sec = new SecService();
|
||||
await sec.updateUserLocale(systemUser.userSystemId, locale);
|
||||
}
|
||||
}
|
||||
|
||||
// Translates the input text if is turned on instance params.
|
||||
|
||||
const originalText = context.text;
|
||||
text = await min.conversationalService.translate(min, text, locale);
|
||||
GBLog.info(`Translated text (processMessageActivity): ${text}.`);
|
||||
context.activity.text = text;
|
||||
context.activity.originalText = originalText;
|
||||
|
||||
// If there is a dialog in course, continue to the next step.
|
||||
|
||||
if (step.activeDialog !== undefined) {
|
||||
await step.continueDialog();
|
||||
} else {
|
||||
let text = context.activity.text;
|
||||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/ig, "");
|
||||
|
||||
// Spells check the input text before translating.
|
||||
|
||||
const key = min.instance.spellcheckerKey ? min.instance.spellcheckerKey : min.instance.spellcheckerKey;
|
||||
if (key) {
|
||||
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||
const data = await AzureText.getSpelledText(min.instance.spellcheckerKey, text);
|
||||
if (data !== text) {
|
||||
GBLog.info(`Spelling corrected: ${data}`);
|
||||
text = data;
|
||||
}
|
||||
}
|
||||
|
||||
let locale = 'en';
|
||||
if (
|
||||
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.
|
||||
locale = await AzureText.getLocale(
|
||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
|
||||
minBoot.instance.textAnalyticsEndpoint
|
||||
? minBoot.instance.textAnalyticsEndpoint
|
||||
: minBoot.instance.textAnalyticsEndpoint,
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
user.locale = locale;
|
||||
await user.save();
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
const notTranslatedQuery = text;
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
text,
|
||||
'en'
|
||||
);
|
||||
GBLog.info(`Translated text (1): ${text}.`);
|
||||
|
||||
// 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 standard kb.gbapp.
|
||||
|
||||
let handled = false;
|
||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
|
@ -825,7 +812,7 @@ export class GBMinService {
|
|||
await e.onExchangeData(min, 'handleAnswer', {
|
||||
query: text,
|
||||
step: step,
|
||||
notTranslatedQuery: notTranslatedQuery,
|
||||
notTranslatedQuery: originalText,
|
||||
message: message ? message['dataValues'] : null,
|
||||
user: user ? user['dataValues'] : null
|
||||
})
|
||||
|
@ -833,7 +820,6 @@ export class GBMinService {
|
|||
handled = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!handled) {
|
||||
await step.beginDialog('/answer', {
|
||||
query: text,
|
||||
|
|
|
@ -10,9 +10,10 @@ export const Messages = {
|
|||
very_sorry_about_error: `I'm sorry to inform that there was an error which was recorded to be solved.`,
|
||||
canceled: 'Canceled. If I can be useful, let me know how',
|
||||
whats_email: "What's your E-mail address?",
|
||||
which_language: "Which language would you like to choose from?",
|
||||
validation_enter_valid_email: "Please enter a valid e-mail." ,
|
||||
affirmative_sentences: /^(sim|s|positivo|afirmativo|claro|evidente|sem dúvida|confirmo|confirmar|confirmado|uhum)/i,
|
||||
|
||||
|
||||
},
|
||||
'pt-BR': {
|
||||
show_video: 'Vou te mostrar um vídeo. Por favor, aguarde...',
|
||||
|
@ -23,6 +24,7 @@ export const Messages = {
|
|||
very_sorry_about_error: `Lamento, ocorreu um erro que já foi registrado para ser tratado.`,
|
||||
canceled: 'Cancelado, avise como posso ser útil novamente.',
|
||||
whats_email: "Qual seu e-mail?",
|
||||
which_language: "Qual idioma você gostaria de usar?",
|
||||
validation_enter_valid_email: "Por favor digite um email válido.",
|
||||
affirmative_sentences: /^(sim|s|positivo|afirmativo|claro|evidente|sem dúvida|confirmo|confirmar|confirmado|uhum)/i,
|
||||
|
||||
|
|
|
@ -106,56 +106,12 @@ export class AskDialog extends IGBDialog {
|
|||
},
|
||||
async step => {
|
||||
if (step.result) {
|
||||
const translatorEnabled = () => {
|
||||
if (min.instance.params) {
|
||||
const params = JSON.parse(min.instance.params);
|
||||
return params ? params['Enable Worldwide Translator'] === 'TRUE' : false;
|
||||
}
|
||||
return false;
|
||||
}; // TODO: Encapsulate.
|
||||
|
||||
let text = step.result;
|
||||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/ig, "");
|
||||
|
||||
let locale = 'en';
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
if (process.env.TRANSLATOR_DISABLED !== 'true' && translatorEnabled()) {
|
||||
locale = await AzureText.getLocale(
|
||||
minBoot.instance.textAnalyticsKey ? minBoot.instance.textAnalyticsKey : minBoot.instance.textAnalyticsKey,
|
||||
minBoot.instance.textAnalyticsEndpoint
|
||||
? minBoot.instance.textAnalyticsEndpoint
|
||||
: minBoot.instance.textAnalyticsEndpoint,
|
||||
text
|
||||
);
|
||||
}
|
||||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/gi, '');
|
||||
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
|
||||
// Spells check the input text before translating.
|
||||
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||
const key = min.instance.spellcheckerKey ? min.instance.spellcheckerKey : min.instance.spellcheckerKey;
|
||||
if (key) {
|
||||
|
||||
const data = await AzureText.getSpelledText(min.instance.spellcheckerKey, text);
|
||||
if (data !== text) {
|
||||
GBLog.info(`Spelling corrected (3): ${data}`);
|
||||
text = data;
|
||||
}
|
||||
}
|
||||
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
user.locale = locale;
|
||||
await user.save();
|
||||
const notTranslatedQuery = text;
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
text,
|
||||
'en'
|
||||
);
|
||||
GBLog.info(`Translated text (3): ${text}.`);
|
||||
|
||||
let handled = false;
|
||||
await CollectionUtil.asyncForEach(min.appPackages, async (e: IGBPackage) => {
|
||||
|
@ -163,7 +119,6 @@ export class AskDialog extends IGBDialog {
|
|||
await e.onExchangeData(min, 'handleAnswer', {
|
||||
query: text,
|
||||
step: step,
|
||||
notTranslatedQuery: notTranslatedQuery,
|
||||
message: text,
|
||||
user: user ? user['dataValues'] : null
|
||||
})
|
||||
|
@ -189,106 +144,92 @@ export class AskDialog extends IGBDialog {
|
|||
private static getAnswerDialog(min: GBMinInstance, service: KBService) {
|
||||
return [
|
||||
async step => {
|
||||
let answer: GuaribasAnswer = null;
|
||||
const user = await min.userProfile.get(step.context, {});
|
||||
let text = step.options.query;
|
||||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/ig, "");
|
||||
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
const userDb = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
// Spells check the input text before translating.
|
||||
|
||||
const key = min.instance.spellcheckerKey ? minBoot.instance.spellcheckerKey : min.instance.spellcheckerKey;
|
||||
if (key) {
|
||||
text = text.charAt(0).toUpperCase() + text.slice(1);
|
||||
const data = await AzureText.getSpelledText(min.instance.spellcheckerKey, text);
|
||||
if (data !== text) {
|
||||
GBLog.info(`Spelling corrected: ${data}`);
|
||||
text = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Translates text before sending Search or NLP.
|
||||
|
||||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
text,
|
||||
userDb.locale ? userDb.locale : 'en'
|
||||
);
|
||||
|
||||
GBLog.info(`Translated text (2): ${text}`);
|
||||
|
||||
let text = step.options.query;
|
||||
text = text.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/gi, '');
|
||||
if (!text) {
|
||||
throw new Error(`/answer being called with no args query text.`);
|
||||
}
|
||||
const locale = step.context.activity.locale;
|
||||
|
||||
// Stops any content on projector.
|
||||
|
||||
await min.conversationalService.sendEvent(min, step, 'stop', undefined);
|
||||
|
||||
// Handle extra text from FAQ.
|
||||
|
||||
if (step.options && step.options.query) {
|
||||
text = step.options.query;
|
||||
} else if (step.options && step.options.fromFaq) {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].going_answer);
|
||||
}
|
||||
|
||||
const searchScore = min.instance.searchScore ? min.instance.searchScore : minBoot.instance.searchScore;
|
||||
// Searches KB for the first time.
|
||||
|
||||
const searchScore = min.instance.searchScore ? min.instance.searchScore : minBoot.instance.searchScore;
|
||||
user.lastQuestion = text;
|
||||
await min.userProfile.set(step.context, user);
|
||||
|
||||
const resultsA = await service.ask(min.instance, text, searchScore, user.subjects);
|
||||
|
||||
// If there is some result, answer immediately.
|
||||
|
||||
if (resultsA !== undefined && resultsA.answer !== undefined) {
|
||||
// Saves some context info.
|
||||
|
||||
user.isAsking = false;
|
||||
user.lastQuestionId = resultsA.questionId;
|
||||
await min.userProfile.set(step.context, user);
|
||||
|
||||
// Sends the answer to all outputs, including projector.
|
||||
|
||||
return await AskDialog.handleAnswer(service, min, step, resultsA.answer);
|
||||
} else {
|
||||
// Second time running Search, now with no filter.
|
||||
answer = resultsA.answer;
|
||||
|
||||
// If this search was restricted to some subjects...
|
||||
} else if (user.subjects) {
|
||||
// ...second time running Search, now with no filter.
|
||||
|
||||
const resultsB = await service.ask(min.instance, text, searchScore, undefined);
|
||||
|
||||
// If there is some result, answer immediately.
|
||||
|
||||
if (resultsB !== undefined && resultsB.answer !== undefined) {
|
||||
if (resultsB !== undefined && resultsB.answer !== undefined)
|
||||
{
|
||||
// Saves some context info.
|
||||
|
||||
const user2 = await min.userProfile.get(step.context, {});
|
||||
user2.isAsking = false;
|
||||
user2.lastQuestionId = resultsB.questionId;
|
||||
await min.userProfile.set(step.context, user2);
|
||||
|
||||
// Informs user that a broader search will be used.
|
||||
|
||||
if (user2.subjects.length > 0) {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].wider_answer);
|
||||
}
|
||||
|
||||
// TODO: Put braces in this IF statment.
|
||||
|
||||
if (resultsB.answer)
|
||||
// Sends the answer to all outputs, including projector.
|
||||
|
||||
return await AskDialog.handleAnswer(service, min, step, resultsA.answer);
|
||||
} else {
|
||||
if (!(await min.conversationalService.routeNLP(step, min, text))) {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].did_not_find);
|
||||
|
||||
return await step.replaceDialog('/ask', { isReturning: true });
|
||||
}
|
||||
answer = resultsB.answer;
|
||||
}
|
||||
}
|
||||
|
||||
// Answers using Search or NLP responses.
|
||||
|
||||
if (answer) {
|
||||
return await AskDialog.handleAnswer(service, min, step, answer);
|
||||
} else if (!(await min.conversationalService.routeNLP(step, min, text))) {
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].did_not_find);
|
||||
return await step.replaceDialog('/ask', { isReturning: true });
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
private static async handleAnswer(service: KBService, min: GBMinInstance, step: any, answer: GuaribasAnswer) {
|
||||
const text = answer.content
|
||||
const text = answer.content;
|
||||
if (text.endsWith('.docx')) {
|
||||
const mainName = GBVMService.getMethodNameFromVBSFilename(text);
|
||||
return await GBVMService.callVM(mainName, min, step, this.deployer);
|
||||
|
|
|
@ -205,8 +205,6 @@ export class KBService implements IGBKBService {
|
|||
|
||||
const values = results.result.value;
|
||||
|
||||
|
||||
|
||||
if (values && values.length > 0 && values[0]['@search.score'] >= searchScore) {
|
||||
const value = await this.getAnswerById(instance.instanceId, values[0].answerId);
|
||||
if (value !== null) {
|
||||
|
@ -216,7 +214,6 @@ export class KBService implements IGBKBService {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
const data = await this.getAnswerByText(instance.instanceId, query);
|
||||
if (data) {
|
||||
return { answer: data.answer, questionId: data.question.questionId };
|
||||
|
@ -288,12 +285,11 @@ export class KBService implements IGBKBService {
|
|||
|
||||
// Finds a valid worksheet because Excel returns empty slots
|
||||
// when loading worksheets collection.
|
||||
|
||||
|
||||
let worksheet: any;
|
||||
for (let t = 0; t < data._worksheets.length; t++) {
|
||||
worksheet = data._worksheets[t];
|
||||
if (worksheet)
|
||||
{
|
||||
if (worksheet) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -302,7 +298,6 @@ export class KBService implements IGBKBService {
|
|||
|
||||
GBLog.info(`Now importing ${rows.length} rows from tabular file ${filePath}...`);
|
||||
return asyncPromise.eachSeries(rows, async line => {
|
||||
|
||||
// Skips the first line.
|
||||
|
||||
if (
|
||||
|
@ -313,7 +308,6 @@ export class KBService implements IGBKBService {
|
|||
line._cells[3] !== undefined &&
|
||||
line._cells[4] !== undefined
|
||||
) {
|
||||
|
||||
// Extracts values from columns in the current line.
|
||||
|
||||
const subjectsText = line._cells[0].text;
|
||||
|
@ -437,20 +431,18 @@ export class KBService implements IGBKBService {
|
|||
step: GBDialogStep,
|
||||
conversationalService: IGBConversationalService
|
||||
) {
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
const user = await min.userProfile.get(step.context, {});
|
||||
|
||||
// Calls language translator.
|
||||
|
||||
let text = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
answer.content,
|
||||
user.locale ? user.locale : 'en'
|
||||
user.systemUser.locale
|
||||
? user.locale
|
||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
GBLog.info(`Translated text(playMarkdown): ${text}.`);
|
||||
|
||||
// Converts from Markdown to HTML.
|
||||
|
||||
|
@ -492,18 +484,6 @@ export class KBService implements IGBKBService {
|
|||
html: string,
|
||||
answer: GuaribasAnswer
|
||||
) {
|
||||
let sec = new SecService();
|
||||
const member = step.context.activity.from;
|
||||
const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
html = await min.conversationalService.translate(
|
||||
min,
|
||||
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
html,
|
||||
user.locale ? user.locale : 'pt'
|
||||
);
|
||||
|
||||
const locale = step.context.activity.locale;
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].will_answer_projector);
|
||||
html = html.replace(/src\=\"kb\//gi, `src=\"../kb/`);
|
||||
|
|
|
@ -10,6 +10,7 @@ import { CollectionUtil } from 'pragmatismo-io-framework';
|
|||
* Security service layer.
|
||||
*/
|
||||
export class SecService extends GBService {
|
||||
|
||||
public async importSecurityFile(localPath: string, instance: IGBInstance) {
|
||||
const security = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'security.json'), 'utf8'));
|
||||
await CollectionUtil.asyncForEach(security.groups, async group => {
|
||||
|
@ -81,6 +82,17 @@ export class SecService extends GBService {
|
|||
await user.save();
|
||||
}
|
||||
|
||||
public async updateUserLocale(userSystemId: number, locale: any) : Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
userSystemId: userSystemId
|
||||
}
|
||||
});
|
||||
user.locale = locale;
|
||||
|
||||
return await user.save();
|
||||
}
|
||||
|
||||
public async updateUserInstance(userSystemId: string, instanceId: number): Promise<GuaribasUser> {
|
||||
let user = await GuaribasUser.findOne({
|
||||
where: {
|
||||
|
@ -171,6 +183,8 @@ export class SecService extends GBService {
|
|||
return agentSystemId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async getUserFromSystemId(systemId: string): Promise<GuaribasUser> {
|
||||
return await GuaribasUser.findOne({
|
||||
where: {
|
||||
|
|
|
@ -419,13 +419,12 @@ export class WhatsappDirectLine extends GBService {
|
|||
await this.sendFileToDevice(to, url, 'Audio', msg);
|
||||
}
|
||||
|
||||
public async sendToDeviceEx(to, msg, locale) {
|
||||
private async sendToDeviceEx(to, text, locale) {
|
||||
const minBoot = GBServer.globals.minBoot as any;
|
||||
|
||||
const text = await this.min.conversationalService.translate(this.min,
|
||||
this.min.instance.translatorKey ? this.min.instance.translatorKey : minBoot.instance.translatorKey,
|
||||
this.min.instance.translatorEndpoint ? this.min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
|
||||
msg,
|
||||
text = await minBoot.conversationalService.translate(
|
||||
minBoot,
|
||||
text,
|
||||
locale
|
||||
);
|
||||
await this.sendToDevice(to, text);
|
||||
|
|
Loading…
Add table
Reference in a new issue