fix(kb.gbapp): /publish review, error handling improved and clean up.
This commit is contained in:
parent
b30e0160c4
commit
c94228cd8d
8 changed files with 148 additions and 159 deletions
|
@ -39,12 +39,13 @@
|
|||
import crypto from 'crypto';
|
||||
import urlJoin from 'url-join';
|
||||
import { WaterfallDialog } from 'botbuilder-dialogs';
|
||||
import { GBMinInstance, IGBDialog, GBLog, IGBPackage } from 'botlib';
|
||||
import { GBMinInstance, IGBDialog } from 'botlib';
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||
import { GBImporter } from '../../core.gbapp/services/GBImporterService.js';
|
||||
import { Messages } from '../strings.js';
|
||||
import { GBAdminService } from '../services/GBAdminService.js';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { SecService } from '../../security.gbapp/services/SecService.js';
|
||||
|
||||
/**
|
||||
* Dialogs for administration tasks.
|
||||
|
@ -144,36 +145,6 @@ export class AdminDialog extends IGBDialog {
|
|||
try {
|
||||
if (text === 'quit') {
|
||||
return await step.replaceDialog('/');
|
||||
} else if (cmdName === 'deployPackage' || cmdName === 'dp') {
|
||||
await GBAdminService.deployPackageCommand(min, text, deployer);
|
||||
|
||||
return await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'redeployPackage' || cmdName === 'rp') {
|
||||
await min.conversationalService.sendText(min, step, 'The package is being *unloaded*...');
|
||||
await GBAdminService.undeployPackageCommand(text, min);
|
||||
await min.conversationalService.sendText(min, step, 'Now, *deploying* package...');
|
||||
await GBAdminService.deployPackageCommand(min, text, deployer);
|
||||
await min.conversationalService.sendText(
|
||||
min,
|
||||
step,
|
||||
'Package deployed. Just need to rebuild the index... Doing it right now.'
|
||||
);
|
||||
await GBAdminService.rebuildIndexPackageCommand(min, deployer);
|
||||
await min.conversationalService.sendText(min, step, 'Finished importing of that .gbkb package. Thanks.');
|
||||
return await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'undeployPackage' || cmdName === 'up') {
|
||||
await min.conversationalService.sendText(min, step, 'The package is being *undeployed*...');
|
||||
await GBAdminService.undeployPackageCommand(text, min);
|
||||
await min.conversationalService.sendText(min, step, 'Package *undeployed*.');
|
||||
return await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'rebuildIndex' || cmdName === 'ri' || cmdName === 'Ri') {
|
||||
await GBAdminService.rebuildIndexPackageCommand(min, deployer);
|
||||
|
||||
return await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'syncBotServer') {
|
||||
await GBAdminService.syncBotServerCommand(min, deployer);
|
||||
|
||||
return await step.replaceDialog('/admin', { firstRun: false });
|
||||
} else if (cmdName === 'setupSecurity') {
|
||||
return await step.beginDialog('/setupSecurity');
|
||||
} else {
|
||||
|
@ -325,18 +296,18 @@ export class AdminDialog extends IGBDialog {
|
|||
packages.push(`${botId}.gbot`);
|
||||
skipError = true;
|
||||
} else {
|
||||
await min.conversationalService.sendText(min, step, `Starting publishing for ${filename}...`);
|
||||
packages.push(filename);
|
||||
}
|
||||
|
||||
|
||||
await CollectionUtil.asyncForEach(packages, async packageName => {
|
||||
let cmd1;
|
||||
|
||||
if (
|
||||
packageName.indexOf('gbdialog') !== -1 ||
|
||||
packageName.indexOf('gbkb') !== -1 ||
|
||||
packageName.indexOf('gbot') !== -1 ||
|
||||
packageName.indexOf('gbtheme') !== -1
|
||||
packageName.toLowerCase() === 'gbdialog' ||
|
||||
packageName.toLowerCase() === 'gbkb' ||
|
||||
packageName.toLowerCase() === 'gbot' ||
|
||||
packageName.toLowerCase() === 'gbtheme'
|
||||
) {
|
||||
packageName = `${min.botId}.${packageName}`;
|
||||
}
|
||||
|
@ -353,10 +324,23 @@ export class AdminDialog extends IGBDialog {
|
|||
const cmd2 = `undeployPackage ${packageName}`;
|
||||
await GBAdminService.undeployPackageCommand(cmd2, min);
|
||||
}
|
||||
await GBAdminService.deployPackageCommand(min, cmd1, deployer);
|
||||
await min.conversationalService.sendText(min, step, `Finished publishing ${packageName}.`);
|
||||
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,
|
||||
null
|
||||
);
|
||||
|
||||
await GBAdminService.deployPackageCommand(min, user, cmd1, deployer);
|
||||
|
||||
});
|
||||
await min.conversationalService.sendText(min, step, Messages[locale].publish_success);
|
||||
await min.conversationalService.sendText(min, step, `Training is finished.`);
|
||||
|
||||
if (!step.activeDialog.state.options.confirm) {
|
||||
return await step.replaceDialog('/ask', { isReturning: true });
|
||||
} else {
|
||||
|
|
|
@ -53,6 +53,7 @@ import { caseSensitive_Numbs_SpecialCharacters_PW, lowercase_PW } from 'super-st
|
|||
import crypto from 'crypto';
|
||||
import Fs from 'fs';
|
||||
import { GBServer } from '../../../src/app.js';
|
||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||
|
||||
/**
|
||||
* Services for server administration.
|
||||
|
@ -138,7 +139,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
public static isSharePointPath(path: string) {
|
||||
return path.indexOf('sharepoint.com') !== -1;
|
||||
}
|
||||
public static async deployPackageCommand(min: GBMinInstance, text: string, deployer: IGBDeployer) {
|
||||
public static async deployPackageCommand(min: GBMinInstance, user: GuaribasUser, text: string, deployer: IGBDeployer) {
|
||||
const packageName = text.split(' ')[1];
|
||||
|
||||
if (!this.isSharePointPath(packageName)) {
|
||||
|
@ -146,7 +147,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
if (additionalPath === undefined) {
|
||||
throw new Error('ADDITIONAL_DEPLOY_PATH is not set and deployPackage was called.');
|
||||
}
|
||||
await deployer.deployPackage(min, urlJoin(additionalPath, packageName));
|
||||
await deployer['deployPackage2'](min, user, urlJoin(additionalPath, packageName));
|
||||
} else {
|
||||
const siteName = text.split(' ')[1];
|
||||
const folderName = text.split(' ')[2];
|
||||
|
@ -157,7 +158,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
// of local resources is required.
|
||||
|
||||
await deployer['downloadFolder'](min, Path.join('work', `${min.instance.botId}.gbai`), Path.basename(folderName));
|
||||
await deployer.deployPackage(min, localFolder);
|
||||
await deployer['deployPackage2'](min, user, localFolder);
|
||||
}
|
||||
}
|
||||
public static async rebuildIndexPackageCommand(min: GBMinInstance, deployer: GBDeployer) {
|
||||
|
|
|
@ -362,15 +362,13 @@ export class GBConversationalService {
|
|||
'content-type': 'application/json',
|
||||
authorization: `Bearer ${min.instance.smsSecret}`
|
||||
},
|
||||
body:
|
||||
JSON.stringify({
|
||||
body: JSON.stringify({
|
||||
numero: `${mobile}`,
|
||||
servico: 'short',
|
||||
mensagem: text,
|
||||
parceiro_id: '',
|
||||
codificacao: '0'
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -383,8 +381,7 @@ export class GBConversationalService {
|
|||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
} else {
|
||||
return new Promise(
|
||||
(resolve: any, reject: any): any => {
|
||||
return new Promise((resolve: any, reject: any): any => {
|
||||
const nexmo = new Nexmo({
|
||||
apiKey: min.instance.smsKey,
|
||||
apiSecret: min.instance.smsSecret
|
||||
|
@ -399,8 +396,7 @@ export class GBConversationalService {
|
|||
resolve(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,9 +435,7 @@ export class GBConversationalService {
|
|||
const transcoder = new prism.FFmpeg({
|
||||
args: ['-analyzeduration', '0', '-loglevel', '0', '-f', 'opus', '-ar', '16000', '-ac', '1']
|
||||
});
|
||||
Fs.createReadStream(waveFilename)
|
||||
.pipe(transcoder)
|
||||
.pipe(output);
|
||||
Fs.createReadStream(waveFilename).pipe(transcoder).pipe(output);
|
||||
|
||||
let url = urlJoin(GBServer.globals.publicAddress, 'audios', oggFilenameOnly);
|
||||
resolve(url);
|
||||
|
@ -528,9 +522,7 @@ export class GBConversationalService {
|
|||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
answer,
|
||||
user.locale
|
||||
? user.locale
|
||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
user.locale ? user.locale : min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
GBLog.verbose(`Translated text(playMarkdown): ${text}.`);
|
||||
}
|
||||
|
@ -851,9 +843,7 @@ export class GBConversationalService {
|
|||
}
|
||||
|
||||
GBLog.info(
|
||||
`NLP called: ${intent}, entities: ${
|
||||
nlp.entities.length
|
||||
}, score: ${score} > required (nlpScore): ${instanceScore}`
|
||||
`NLP called: ${intent}, entities: ${nlp.entities.length}, score: ${score} > required (nlpScore): ${instanceScore}`
|
||||
);
|
||||
|
||||
step.activeDialog.state.options.entities = nlp.entities;
|
||||
|
@ -956,10 +946,14 @@ export class GBConversationalService {
|
|||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
} else {
|
||||
const url = urlJoin(endPoint, 'translate', new URLSearchParams({
|
||||
const url = urlJoin(
|
||||
endPoint,
|
||||
'translate',
|
||||
new URLSearchParams({
|
||||
'api-version': '3.0',
|
||||
to: language
|
||||
}).toString());
|
||||
}).toString()
|
||||
);
|
||||
let options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -992,9 +986,7 @@ export class GBConversationalService {
|
|||
text = await min.conversationalService.translate(
|
||||
min,
|
||||
text,
|
||||
user.locale
|
||||
? user.locale
|
||||
: min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
user.locale ? user.locale : min.core.getParam<string>(min.instance, 'Locale', GBConfigService.get('LOCALE'))
|
||||
);
|
||||
GBLog.verbose(`Translated text(prompt): ${text}.`);
|
||||
}
|
||||
|
@ -1013,10 +1005,15 @@ export class GBConversationalService {
|
|||
const member = step.context.activity.from;
|
||||
let sec = new SecService();
|
||||
let user = await sec.getUserFromSystemId(step.context.activity.from.id);
|
||||
await this['sendTextWithOptionsAndUser'](min, user, step, text, true, null);
|
||||
}
|
||||
|
||||
public async sendTextWithOptionsAndUser(min: GBMinInstance, user, step, text, translate, keepTextList) {
|
||||
const member = step ? step.context.activity.from : null;
|
||||
|
||||
if (translate) {
|
||||
let replacements = [];
|
||||
|
||||
if (translate) {
|
||||
// To fix MSFT bug.
|
||||
|
||||
if (keepTextList) {
|
||||
|
@ -1058,7 +1055,7 @@ export class GBConversationalService {
|
|||
}
|
||||
analytics.createMessage(min.instance.instanceId, conversation, null, text);
|
||||
|
||||
if (!isNaN(member.id) && !member.id.startsWith('1000')) {
|
||||
if (member && !isNaN(member.id) && !member.id.startsWith('1000')) {
|
||||
const to = step.context.activity.group ? step.context.activity.group : member.id;
|
||||
|
||||
await min.whatsAppDirectLine.sendToDevice(to, text, step.context.activity.conversation.id);
|
||||
|
@ -1066,7 +1063,6 @@ export class GBConversationalService {
|
|||
await step.context.sendActivity(text);
|
||||
}
|
||||
}
|
||||
|
||||
public async broadcast(min: GBMinInstance, message: string) {
|
||||
GBLog.info(`Sending broadcast notifications...`);
|
||||
|
||||
|
|
|
@ -559,11 +559,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
instanceId: instanceId
|
||||
});
|
||||
}
|
||||
|
||||
public async deployPackage(min: GBMinInstance, localPath: string) {
|
||||
// TODO: @alanperdomo: Adjust interface mismatch.
|
||||
}
|
||||
/**
|
||||
* Deploys a folder into the bot storage.
|
||||
*/
|
||||
public async deployPackage(min: GBMinInstance, localPath: string) {
|
||||
public async deployPackage2(min: GBMinInstance, user, localPath: string) {
|
||||
const packageType = Path.extname(localPath);
|
||||
let handled = false;
|
||||
let pck = null;
|
||||
|
@ -717,7 +719,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
try {
|
||||
GBLogEx.info(instance.instanceId, `Acquiring rebuildIndex mutex...`);
|
||||
release = await GBServer.globals.indexSemaphore.acquire();
|
||||
|
||||
GBLogEx.info(instance.instanceId, `Acquire rebuildIndex done.`);
|
||||
const search = new AzureSearch(
|
||||
instance.searchKey,
|
||||
instance.searchHost,
|
||||
|
@ -729,7 +731,11 @@ export class GBDeployer implements IGBDeployer {
|
|||
try {
|
||||
await search.createDataSource(dsName, dsName, 'GuaribasQuestion', 'azuresql', connectionString);
|
||||
} catch (err) {
|
||||
GBLog.error(err);
|
||||
// If it is a 404 there is nothing to delete as it is the first creation.
|
||||
|
||||
if (err.code !== 400 && err.message.indexOf('already exists') !==-1) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Removes the index.
|
||||
|
@ -739,11 +745,11 @@ export class GBDeployer implements IGBDeployer {
|
|||
} catch (err) {
|
||||
// If it is a 404 there is nothing to delete as it is the first creation.
|
||||
|
||||
if (err.code !== 404 && err.code !== 'OperationNotAllowed') {
|
||||
if (err.code !== 'ResourceNameAlreadyInUse') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
GBLogEx.info(instance.instanceId, `Acquire rebuildIndex done.`);
|
||||
await search.rebuildIndex(instance.searchIndexer);
|
||||
release();
|
||||
GBLogEx.info(instance.instanceId, `Released rebuildIndex mutex.`);
|
||||
|
|
|
@ -282,26 +282,27 @@ export class GBMinService {
|
|||
// min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
|
||||
|
||||
GBServer.globals.minInstances.push(min);
|
||||
const user = null; // No user context.
|
||||
|
||||
await this.deployer.deployPackage(min, 'packages/default.gbtheme');
|
||||
await this.deployer['deployPackage2'](min, user, 'packages/default.gbtheme');
|
||||
|
||||
// Install per bot deployed packages.
|
||||
|
||||
let packagePath = `work/${min.botId}.gbai/${min.botId}.gbdialog`;
|
||||
if (Fs.existsSync(packagePath)) {
|
||||
await this.deployer.deployPackage(min, packagePath);
|
||||
await this.deployer['deployPackage2'](min, user, packagePath);
|
||||
}
|
||||
packagePath = `work/${min.botId}.gbai/${min.botId}.gbapp`;
|
||||
if (Fs.existsSync(packagePath)) {
|
||||
await this.deployer.deployPackage(min, packagePath);
|
||||
await this.deployer['deployPackage2'](min, user, packagePath);
|
||||
}
|
||||
packagePath = `work/${min.botId}.gbai/${min.botId}.gbtheme`;
|
||||
if (Fs.existsSync(packagePath)) {
|
||||
await this.deployer.deployPackage(min, packagePath);
|
||||
await this.deployer['deployPackage2'](min, user, packagePath);
|
||||
}
|
||||
packagePath = `work/${min.botId}.gbai/${min.botId}.gblib`;
|
||||
if (Fs.existsSync(packagePath)) {
|
||||
await this.deployer.deployPackage(min, packagePath);
|
||||
await this.deployer['deployPackage2'](min, user, packagePath);
|
||||
}
|
||||
|
||||
let dir = `work/${min.botId}.gbai/cache`;
|
||||
|
@ -375,6 +376,7 @@ export class GBMinService {
|
|||
};
|
||||
|
||||
await CollectionUtil.asyncForEach(steps, async step => {
|
||||
|
||||
client.apis.Conversations.Conversations_PostActivity({
|
||||
conversationId: conversationId,
|
||||
activity: {
|
||||
|
@ -388,7 +390,7 @@ export class GBMinService {
|
|||
}
|
||||
});
|
||||
|
||||
await sleep(5000);
|
||||
await sleep(3000);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -65,53 +65,52 @@ export class GuaribasSubject extends Model<GuaribasSubject> {
|
|||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column(DataType.INTEGER)
|
||||
subjectId: number;
|
||||
|
||||
@Column(DataType.INTEGER)
|
||||
internalId: string;
|
||||
declare subjectId: number;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
title: string;
|
||||
declare internalId: string;
|
||||
|
||||
declare title: string;
|
||||
|
||||
@Column(DataType.STRING(512))
|
||||
description: string;
|
||||
declare description: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
from: string;
|
||||
declare from: string;
|
||||
|
||||
@Column(DataType.STRING(255))
|
||||
to: string;
|
||||
declare to: string;
|
||||
|
||||
@ForeignKey(() => GuaribasSubject)
|
||||
@Column(DataType.INTEGER)
|
||||
parentSubjectId: number;
|
||||
declare parentSubjectId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasSubject, 'parentSubjectId')
|
||||
parentSubject: GuaribasSubject;
|
||||
|
||||
@HasMany(() => GuaribasSubject, { foreignKey: 'parentSubjectId' })
|
||||
childrenSubjects: GuaribasSubject[];
|
||||
declare childrenSubjects: GuaribasSubject[];
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column(DataType.INTEGER)
|
||||
instanceId: number;
|
||||
declare instanceId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasInstance)
|
||||
instance: GuaribasInstance;
|
||||
declare instance: GuaribasInstance;
|
||||
|
||||
@ForeignKey(() => GuaribasUser)
|
||||
@Column(DataType.INTEGER)
|
||||
responsibleUserId: number;
|
||||
declare responsibleUserId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasUser)
|
||||
responsibleUser: GuaribasUser;
|
||||
declare responsibleUser: GuaribasUser;
|
||||
|
||||
@ForeignKey(() => GuaribasPackage)
|
||||
@Column(DataType.INTEGER)
|
||||
packageId: number;
|
||||
declare packageId: number;
|
||||
|
||||
@BelongsTo(() => GuaribasPackage)
|
||||
package: GuaribasPackage;
|
||||
declare package: GuaribasPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -869,8 +869,9 @@ export class KBService implements IGBKBService {
|
|||
|
||||
let level;
|
||||
for (level = 0; level < MAX_LEVEL; level++) {
|
||||
menu = row._cells[level];
|
||||
if (menu && menu.text) {
|
||||
const cell = row._cells[level];
|
||||
if (cell && cell.text) {
|
||||
menu = cell.text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -890,10 +891,10 @@ export class KBService implements IGBKBService {
|
|||
activeChildrenGivenLevel[level] = childrenNode;
|
||||
|
||||
// Insert the object into JSON.
|
||||
|
||||
const description = row._cells[level + 1]?row._cells[level + 1].text: null;
|
||||
activeObj = {
|
||||
title: menu,
|
||||
description: row._cells[level + 1],
|
||||
description: description,
|
||||
id: menu,
|
||||
children: []
|
||||
};
|
||||
|
@ -984,7 +985,7 @@ export class KBService implements IGBKBService {
|
|||
min['groupCache'] = await KBService.getGroupReplies(instance.instanceId);
|
||||
await KBService.RefreshNER(min);
|
||||
|
||||
GBLog.info(`[GBDeployer] Opening package: ${localPath}`);
|
||||
GBLog.info(`[GBDeployer] Start Bot Server Side Rendering... ${localPath}`);
|
||||
const html = await GBSSR.getHTML(min);
|
||||
const path = Path.join(
|
||||
process.env.PWD,
|
||||
|
@ -993,7 +994,7 @@ export class KBService implements IGBKBService {
|
|||
`${min.instance.botId}.gbui`,
|
||||
'index.html'
|
||||
);
|
||||
GBLogEx.info(min, `[GBDeployer] Generating SSR HTML in ${path}.`);
|
||||
GBLogEx.info(min, `[GBDeployer] Saving SSR HTML in ${path}.`);
|
||||
Fs.writeFileSync(path, html, 'utf8');
|
||||
|
||||
GBLog.info(`[GBDeployer] Finished import of ${localPath}`);
|
||||
|
|
|
@ -103,11 +103,11 @@ export class GBServer {
|
|||
server.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
process.on('unhandledRejection', (err, p) => {
|
||||
GBLog.error(`UNHANDLED_REJECTION(promises): ${p} ${err.toString()}`);
|
||||
GBLog.error(`UNHANDLED_REJECTION(promises): ${err.toString()} ${err['stack']?'\n'+err['stack']:''}`);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (err, origin) => {
|
||||
GBLog.error(`UNCAUGHT_EXCEPTION: ${err.toString()}`);
|
||||
process.on('uncaughtException', (err, p) => {
|
||||
GBLog.error(`UNCAUGHT_EXCEPTION: ${err.toString()} ${err['stack']?'\n'+err['stack']:''}`);
|
||||
});
|
||||
|
||||
// Creates working directory.
|
||||
|
|
Loading…
Add table
Reference in a new issue