new(all): Log per bot started. #299.

This commit is contained in:
rodrigorodriguez 2023-02-12 14:31:21 -03:00
parent b7cad9a67f
commit 3d500051fa
8 changed files with 197 additions and 79 deletions

View file

@ -238,6 +238,24 @@ export class AdminDialog extends IGBDialog {
]) ])
); );
min.dialogs.add(
new WaterfallDialog('/logs', [
async step => {
if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) {
return await step.beginDialog('/auth');
} else {
return await step.next(step.options);
}
},
async step => {
const logs = await min.core['getLatestLogs']();
await min.conversationalService.sendText(min, step, logs);
return await step.replaceDialog('/ask', { isReturning: true });
}
]));
min.dialogs.add( min.dialogs.add(
new WaterfallDialog('/publish', [ new WaterfallDialog('/publish', [
async step => { async step => {

View file

@ -32,7 +32,7 @@
'use strict'; 'use strict';
import { GBLog, GBMinInstance, GBService, IGBCoreService, GBDialogStep } from 'botlib'; import { GBMinInstance, GBService, IGBCoreService, GBDialogStep } from 'botlib';
import * as Fs from 'fs'; import * as Fs from 'fs';
import { GBServer } from '../../../src/app.js'; import { GBServer } from '../../../src/app.js';
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js'; import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
@ -50,9 +50,7 @@ import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
import pkg from 'swagger-client'; import pkg from 'swagger-client';
import { DialogKeywords } from './DialogKeywords.js'; import { DialogKeywords } from './DialogKeywords.js';
import { KeywordsExpressions } from './KeywordsExpressions.js'; import { KeywordsExpressions } from './KeywordsExpressions.js';
const { Swagger } = pkg; import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
/** /**
* @fileoverview Decision was to priorize security(isolation) and debugging, * @fileoverview Decision was to priorize security(isolation) and debugging,
@ -129,7 +127,7 @@ export class GBVMService extends GBService {
}`; }`;
Fs.writeFileSync(urlJoin(folder, 'package.json'), packageJson); Fs.writeFileSync(urlJoin(folder, 'package.json'), packageJson);
GBLog.info(`BASIC: Installing .gbdialog node_modules for ${min.botId}...`); GBLogEx.info(min, `BASIC: Installing .gbdialog node_modules for ${min.botId}...`);
const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm'); const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm');
child_process.execSync(`${npmPath} install`, { cwd: folder }); child_process.execSync(`${npmPath} install`, { cwd: folder });
} }
@ -139,7 +137,7 @@ export class GBVMService extends GBService {
const fullFilename = urlJoin(folder, filename); const fullFilename = urlJoin(folder, filename);
if (process.env.GBDIALOG_HOTSWAP) { if (process.env.GBDIALOG_HOTSWAP) {
Fs.watchFile(fullFilename, async () => { Fs.watchFile(fullFilename, async () => {
await this.translateBASIC(fullFilename, mainName, min.botId); await this.translateBASIC(fullFilename, mainName, min);
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
}); });
@ -152,10 +150,10 @@ export class GBVMService extends GBService {
const jsStat = Fs.statSync(jsfile); const jsStat = Fs.statSync(jsfile);
const interval = 30000; // If compiled is older 30 seconds, then recompile. const interval = 30000; // If compiled is older 30 seconds, then recompile.
if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) { if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) {
await this.translateBASIC(fullFilename, mainName, min.botId); await this.translateBASIC(fullFilename, mainName, min);
} }
} else { } else {
await this.translateBASIC(fullFilename, mainName, min.botId); await this.translateBASIC(fullFilename, mainName, min);
} }
const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); const parsedCode: string = Fs.readFileSync(jsfile, 'utf8');
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
@ -163,7 +161,7 @@ export class GBVMService extends GBService {
}); });
} }
public async translateBASIC(filename: any, mainName: string, botId: string) { public async translateBASIC(filename: any, mainName: string, min:GBMinInstance) {
// Converts General Bots BASIC into regular VBS // Converts General Bots BASIC into regular VBS
let basicCode: string = Fs.readFileSync(filename, 'utf8'); let basicCode: string = Fs.readFileSync(filename, 'utf8');
@ -204,10 +202,10 @@ export class GBVMService extends GBService {
// Interprocess communication from local HTTP to the BotServer. // Interprocess communication from local HTTP to the BotServer.
const dk = rest.createClient('http://localhost:1111/api/v2/${botId}/dialog'); const dk = rest.createClient('http://localhost:1111/api/v2/${min.botId}/dialog');
const sys = rest.createClient('http://localhost:1111/api/v2/${botId}/system'); const sys = rest.createClient('http://localhost:1111/api/v2/${min.botId}/system');
const wa = rest.createClient('http://localhost:1111/api/v2/${botId}/webautomation'); const wa = rest.createClient('http://localhost:1111/api/v2/${min.botId}/webautomation');
const img = rest.createClient('http://localhost:1111/api/v2/${botId}/imagprocessing'); const img = rest.createClient('http://localhost:1111/api/v2/${min.botId}/imagprocessing');
// Local variables. // Local variables.
@ -245,7 +243,7 @@ export class GBVMService extends GBService {
`; `;
Fs.writeFileSync(jsfile, code); Fs.writeFileSync(jsfile, code);
GBLog.info(`[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${code}`); GBLogEx.info(min, `[GBVMService] Finished loading of ${filename}, JavaScript from Word: \n ${code}`);
} }
public static getMethodNameFromVBSFilename(filename: string) { public static getMethodNameFromVBSFilename(filename: string) {
@ -288,7 +286,7 @@ export class GBVMService extends GBService {
public async convert(code: string) { public async convert(code: string) {
// Start and End of VB2TS tags of processing. // Start and End of VB2TS tags of processing.
code = process.env.ENABLE_AUTH ? `hear gbLogin as login\n${code}` : code; code = process.env.ENABLE_AUTH ? `hear GBLogExin as login\n${code}` : code;
var lines = code.split('\n'); var lines = code.split('\n');
const keywords = KeywordsExpressions.getKeywords(); const keywords = KeywordsExpressions.getKeywords();
let current = 41; let current = 41;

View file

@ -43,7 +43,7 @@ import { LanguageDialog } from './dialogs/LanguageDialog.js';
import { SwitchBotDialog } from './dialogs/SwitchBot.js'; import { SwitchBotDialog } from './dialogs/SwitchBot.js';
import { WelcomeDialog } from './dialogs/WelcomeDialog.js'; import { WelcomeDialog } from './dialogs/WelcomeDialog.js';
import { WhoAmIDialog } from './dialogs/WhoAmIDialog.js'; import { WhoAmIDialog } from './dialogs/WhoAmIDialog.js';
import { GuaribasChannel, GuaribasException, GuaribasInstance, GuaribasPackage } from './models/GBModel.js'; import { GuaribasChannel, GuaribasInstance, GuaribasLog, GuaribasPackage } from './models/GBModel.js';
/** /**
* Package for core.gbapp. * Package for core.gbapp.
@ -53,7 +53,7 @@ export class GBCorePackage implements IGBPackage {
public CurrentEngineName = 'guaribas-1.0.0'; public CurrentEngineName = 'guaribas-1.0.0';
public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> { public async loadPackage (core: IGBCoreService, sequelize: Sequelize): Promise<void> {
core.sequelize.addModels([GuaribasInstance, GuaribasPackage, GuaribasChannel, GuaribasException]); core.sequelize.addModels([GuaribasInstance, GuaribasPackage, GuaribasChannel, GuaribasLog]);
} }
public async getDialogs (min: GBMinInstance) { public async getDialogs (min: GBMinInstance) {

View file

@ -326,15 +326,18 @@ export class GuaribasChannel extends Model<GuaribasChannel> {
*/ */
@Table @Table
//tslint:disable-next-line:max-classes-per-file //tslint:disable-next-line:max-classes-per-file
export class GuaribasException extends Model<GuaribasException> { export class GuaribasLog extends Model<GuaribasLog> {
@PrimaryKey @PrimaryKey
@AutoIncrement @AutoIncrement
@Column(DataType.INTEGER) @Column(DataType.INTEGER)
declare exceptionId: number; declare logId: number;
@Column(DataType.STRING(255)) @Column(DataType.STRING(1024))
declare message: string; declare message: string;
@Column(DataType.STRING(1))
declare kind: string;
@ForeignKey(() => GuaribasInstance) @ForeignKey(() => GuaribasInstance)
@Column(DataType.INTEGER) @Column(DataType.INTEGER)
declare instanceId: number; declare instanceId: number;

View file

@ -50,7 +50,7 @@ import { GBCustomerSatisfactionPackage } from '../../customer-satisfaction.gbapp
import { GBKBPackage } from '../../kb.gbapp/index.js'; import { GBKBPackage } from '../../kb.gbapp/index.js';
import { GBSecurityPackage } from '../../security.gbapp/index.js'; import { GBSecurityPackage } from '../../security.gbapp/index.js';
import { GBWhatsappPackage } from '../../whatsapp.gblib/index.js'; import { GBWhatsappPackage } from '../../whatsapp.gblib/index.js';
import { GuaribasInstance } from '../models/GBModel.js'; import { GuaribasInstance, GuaribasLog} from '../models/GBModel.js';
import { GBConfigService } from './GBConfigService.js'; import { GBConfigService } from './GBConfigService.js';
import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp/index.js'; import { GBAzureDeployerPackage } from '../../azuredeployer.gbapp/index.js';
import { GBSharePointPackage } from '../../sharepoint.gblib/index.js'; import { GBSharePointPackage } from '../../sharepoint.gblib/index.js';
@ -210,6 +210,28 @@ export class GBCoreService implements IGBCoreService {
} }
} }
/**
* Loads all items to start several listeners.
*/
public async getLatestLogs(instanceId: number): Promise<string> {
const options = {
where: {
instanceId: instanceId,
state: 'active',
created: {
[Op.gt]: new Date(Date.now() - 60 * 60 * 1000 * 48) // Latest 48 hours.
}
}
};
const list = await GuaribasLog.findAll(options);
let out = 'General Bots Log\n';
await CollectionUtil.asyncForEach(list, async e => {
out = `${out}\n${e.createdAt} - ${e.message}`;
});
return out;
}
/** /**
* Loads all items to start several listeners. * Loads all items to start several listeners.
*/ */
@ -547,17 +569,12 @@ ENDPOINT_UPDATE=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,
(match: string, ...args: any[]): string => {
return `CONSTRAINT [${table}_pk] ${match}`; return `CONSTRAINT [${table}_pk] ${match}`;
} });
);
const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g; const re3 = /FOREIGN\s+KEY\s+\((\[[^\]]*\](?:,\s*\[[^\]]*\])*)\)/g;
const re4 = /\[([^\]]*)\]/g; const re4 = /\[([^\]]*)\]/g;
sql = sql.replace( sql = sql.replace(re3, (match: string, ...args: any[]): string => {
re3,
(match: string, ...args: any[]): string => {
const fkcols = args[0]; const fkcols = args[0];
let fkname = table; let fkname = table;
let matches2 = re4.exec(fkcols); let matches2 = re4.exec(fkcols);
@ -567,8 +584,7 @@ ENDPOINT_UPDATE=true
} }
return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`; return `CONSTRAINT [${fkname}_fk] FOREIGN KEY (${fkcols})`;
} });
);
} }
return sql; return sql;
@ -590,9 +606,7 @@ ENDPOINT_UPDATE=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,
(match: string, ...args: any[]): string => {
const fkcols = args[2]; const fkcols = args[2];
let fkname = table; let fkname = table;
let matches2 = re3.exec(fkcols); let matches2 = re3.exec(fkcols);
@ -602,8 +616,7 @@ ENDPOINT_UPDATE=true
} }
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;

View file

@ -0,0 +1,85 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ _ _ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/ \ /`\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| |*| |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| 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 { GBLog, IGBInstance } from "botlib";
import { GuaribasLog } from "../models/GBModel";
export class GBLogEx {
public static async error(minOrInstanceId: any, message: string) {
GBLog.error(message);
if (typeof minOrInstanceId === 'object') {
minOrInstanceId = minOrInstanceId.instance.instanceId;
}
await this.log(minOrInstanceId, 'e', message);
}
public static async debug(minOrInstanceId: any, message: string) {
GBLog.debug(message);
if (typeof minOrInstanceId === 'object') {
minOrInstanceId = minOrInstanceId.instance.instanceId;
}
await this.log(minOrInstanceId, 'd', message);
}
public static async info(minOrInstanceId: any, message: string) {
GBLog.info(message);
if (typeof minOrInstanceId === 'object') {
minOrInstanceId = minOrInstanceId.instance.instanceId;
}
await this.log(minOrInstanceId, 'i', message);
}
public static async verbose(minOrInstanceId: any, message: string) {
GBLog.verbose(message);
if (typeof minOrInstanceId === 'object') {
minOrInstanceId = minOrInstanceId.instance.instanceId;
}
await this.log(minOrInstanceId, 'v', message);
}
/**
* Finds and update user agent information to a next available person.
*/
public static async log(instance: IGBInstance, kind: string, message: string): Promise<GuaribasLog> {
return await GuaribasLog.create(<GuaribasLog>{
instanceId: instance.instanceId,
message: message,
kind: kind
});
}
}

View file

@ -101,7 +101,7 @@ export class AskDialog extends IGBDialog {
if (step.options && step.options.firstTime) { if (step.options && step.options.firstTime) {
text = Messages[locale].ask_first_time; text = Messages[locale].ask_first_time;
} else if (step.options && step.options.isReturning) { } else if (step.options && step.options.isReturning) {
text = ''; // REMOVED: Messages[locale].anything_else; text = Messages[locale].anything_else;
} else if (step.options && step.options.emptyPrompt) { } else if (step.options && step.options.emptyPrompt) {
text = ''; text = '';
} else if (user.subjects.length > 0) { } else if (user.subjects.length > 0) {

View file

@ -29,6 +29,7 @@
| our trademarks remain entirely with us. | | our trademarks remain entirely with us. |
| | | |
\*****************************************************************************/ \*****************************************************************************/
/** /**
* @fileoverview General Bots server core. * @fileoverview General Bots server core.
*/ */