2018-04-21 02:59:30 -03:00
|
|
|
|
/*****************************************************************************\
|
2024-01-09 17:40:48 -03:00
|
|
|
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
|
|
|
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
|
|
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
|
|
|
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
|
|
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
2018-04-21 02:59:30 -03:00
|
|
|
|
| |
|
2024-08-17 20:30:00 -03:00
|
|
|
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
2018-04-21 02:59:30 -03:00
|
|
|
|
| Licensed under the AGPL-3.0. |
|
2018-11-11 19:09:18 -02:00
|
|
|
|
| |
|
2018-04-21 02:59:30 -03:00
|
|
|
|
| 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, |
|
2018-09-11 19:40:53 -03:00
|
|
|
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
2018-04-21 02:59:30 -03:00
|
|
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
|
| GNU Affero General Public License for more details. |
|
|
|
|
|
| |
|
2024-08-17 20:30:00 -03:00
|
|
|
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
2018-04-21 02:59:30 -03:00
|
|
|
|
| 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. |
|
|
|
|
|
| |
|
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
|
2018-11-26 14:09:09 -02:00
|
|
|
|
'use strict';
|
|
|
|
|
|
2023-12-29 21:43:48 -03:00
|
|
|
|
import { GBMinInstance, GBService, IGBCoreService, GBLog } from 'botlib';
|
2024-09-15 14:41:56 -03:00
|
|
|
|
import fs from 'fs/promises';
|
2024-08-21 13:09:50 -03:00
|
|
|
|
import * as ji from 'just-indent';
|
2023-01-13 13:30:18 -03:00
|
|
|
|
import { GBServer } from '../../../src/app.js';
|
2022-11-18 22:39:14 -03:00
|
|
|
|
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
2020-06-14 21:40:41 -03:00
|
|
|
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
2022-11-18 22:39:14 -03:00
|
|
|
|
import { ScheduleServices } from './ScheduleServices.js';
|
|
|
|
|
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
|
|
|
|
import urlJoin from 'url-join';
|
|
|
|
|
import { NodeVM, VMScript } from 'vm2';
|
|
|
|
|
import { createVm2Pool } from './vm2-process/index.js';
|
2024-09-07 18:13:36 -03:00
|
|
|
|
import { watch } from 'fs';
|
2022-11-18 22:39:14 -03:00
|
|
|
|
import textract from 'textract';
|
|
|
|
|
import walkPromise from 'walk-promise';
|
|
|
|
|
import child_process from 'child_process';
|
2024-09-06 15:30:03 -03:00
|
|
|
|
import path from 'path';
|
2023-01-13 13:30:18 -03:00
|
|
|
|
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
2023-01-13 16:09:45 -03:00
|
|
|
|
import { DialogKeywords } from './DialogKeywords.js';
|
2023-02-04 10:45:30 -03:00
|
|
|
|
import { KeywordsExpressions } from './KeywordsExpressions.js';
|
2023-02-12 14:31:21 -03:00
|
|
|
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
2023-02-22 16:06:57 -03:00
|
|
|
|
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
2023-03-04 16:27:25 -03:00
|
|
|
|
import { SystemKeywords } from './SystemKeywords.js';
|
2023-12-29 21:43:48 -03:00
|
|
|
|
import { Sequelize, QueryTypes } from '@sequelize/core';
|
2024-08-21 13:09:50 -03:00
|
|
|
|
import { z } from 'zod';
|
|
|
|
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
2024-09-06 15:15:42 -03:00
|
|
|
|
import { GBUtil } from '../../../src/util.js';
|
2023-12-29 21:43:48 -03:00
|
|
|
|
|
2018-11-11 19:09:18 -02:00
|
|
|
|
/**
|
2022-11-19 23:34:58 -03:00
|
|
|
|
* @fileoverview Decision was to priorize security(isolation) and debugging,
|
2022-11-10 10:39:05 -03:00
|
|
|
|
* over a beautiful BASIC transpiler (to be done).
|
2018-11-11 19:09:18 -02:00
|
|
|
|
*/
|
|
|
|
|
|
2019-03-09 16:59:31 -03:00
|
|
|
|
/**
|
|
|
|
|
* Basic services for BASIC manipulation.
|
|
|
|
|
*/
|
2019-03-08 06:37:13 -03:00
|
|
|
|
export class GBVMService extends GBService {
|
2023-02-04 10:45:30 -03:00
|
|
|
|
private static DEBUGGER_PORT = 9222;
|
2023-03-05 11:09:36 -03:00
|
|
|
|
public static API_PORT = 1111;
|
2023-02-04 10:45:30 -03:00
|
|
|
|
|
2023-01-13 16:09:45 -03:00
|
|
|
|
public async loadDialogPackage(folder: string, min: GBMinInstance, core: IGBCoreService, deployer: GBDeployer) {
|
2024-09-06 15:30:03 -03:00
|
|
|
|
const ignore = path.join('work', GBUtil.getGBAIPath(min.botId, 'gbdialog'), 'node_modules');
|
2024-08-21 13:09:50 -03:00
|
|
|
|
const files = await walkPromise(folder, { ignore: [ignore] });
|
2019-02-23 13:17:21 -03:00
|
|
|
|
|
2020-06-14 21:40:41 -03:00
|
|
|
|
await CollectionUtil.asyncForEach(files, async file => {
|
|
|
|
|
if (!file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let filename: string = file.name;
|
|
|
|
|
|
2024-08-21 13:09:50 -03:00
|
|
|
|
filename = await this.loadDialog(filename, folder, min);
|
2023-02-22 13:18:16 -03:00
|
|
|
|
});
|
|
|
|
|
}
|
2021-08-09 17:55:55 -03:00
|
|
|
|
|
2023-10-20 13:39:34 -03:00
|
|
|
|
public static compare(obj1, obj2) {
|
|
|
|
|
//check for obj2 overlapping props
|
|
|
|
|
if (!Object.keys(obj2).every(key => obj1.hasOwnProperty(key))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//check every key for being same
|
|
|
|
|
return Object.keys(obj1).every(function (key) {
|
|
|
|
|
//if object
|
2024-08-21 13:09:50 -03:00
|
|
|
|
if (typeof obj1[key] == 'object' && typeof obj2[key] == 'object') {
|
2023-10-20 13:39:34 -03:00
|
|
|
|
//recursively check
|
|
|
|
|
return GBVMService.compare(obj1[key], obj2[key]);
|
|
|
|
|
} else {
|
|
|
|
|
//do the normal compare
|
|
|
|
|
return obj1[key] === obj2[key];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 13:18:16 -03:00
|
|
|
|
public async loadDialog(filename: string, folder: string, min: GBMinInstance) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
const isWord = filename.endsWith('.docx');
|
|
|
|
|
if (
|
|
|
|
|
!(
|
|
|
|
|
isWord ||
|
|
|
|
|
filename.endsWith('.vbs') ||
|
|
|
|
|
filename.endsWith('.vb') ||
|
|
|
|
|
filename.endsWith('.vba') ||
|
|
|
|
|
filename.endsWith('.bas') ||
|
|
|
|
|
filename.endsWith('.basic')
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-08-20 19:12:57 -03:00
|
|
|
|
|
2023-02-22 13:18:16 -03:00
|
|
|
|
const wordFile = filename;
|
2024-08-21 13:09:50 -03:00
|
|
|
|
const vbsFile = isWord ? filename.substr(0, filename.indexOf('docx')) + 'vbs' : filename;
|
2023-02-22 13:18:16 -03:00
|
|
|
|
const fullVbsFile = urlJoin(folder, vbsFile);
|
2024-09-15 14:41:56 -03:00
|
|
|
|
const docxStat = await fs.stat(urlJoin(folder, wordFile));
|
2023-02-22 13:18:16 -03:00
|
|
|
|
const interval = 3000; // If compiled is older 30 seconds, then recompile.
|
|
|
|
|
let writeVBS = true;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2024-04-01 13:00:47 -03:00
|
|
|
|
// TODO: #412.
|
|
|
|
|
// const subscription = {
|
|
|
|
|
// changeType: 'created,updated',
|
|
|
|
|
// notificationUrl: 'https://webhook.azurewebsites.net/notificationClient',
|
|
|
|
|
// lifecycleNotificationUrl: 'https://webhook.azurewebsites.net/api/lifecycleNotifications',
|
|
|
|
|
// resource: '/me/mailfolders(\'inbox\')/messages',
|
|
|
|
|
// expirationDateTime: '2016-03-20T11:00:00.0000000Z',
|
|
|
|
|
// clientState: 'SecretClientState'
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
2024-08-21 13:09:50 -03:00
|
|
|
|
|
2024-04-01 13:00:47 -03:00
|
|
|
|
// await client.api('/subscriptions')
|
|
|
|
|
// .post(subscription);
|
2024-04-01 11:55:45 -03:00
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
if (await GBUtil.exists(fullVbsFile)) {
|
2024-09-15 14:41:56 -03:00
|
|
|
|
const vbsStat = await fs.stat(fullVbsFile);
|
2023-02-22 13:18:16 -03:00
|
|
|
|
if (docxStat['mtimeMs'] < vbsStat['mtimeMs'] + interval) {
|
|
|
|
|
writeVBS = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
filename = vbsFile;
|
|
|
|
|
let mainName = GBVMService.getMethodNameFromVBSFilename(filename);
|
|
|
|
|
min.scriptMap[filename] = mainName;
|
2020-05-14 12:46:57 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
if (writeVBS && GBConfigService.get('STORAGE_NAME')) {
|
2023-02-22 13:18:16 -03:00
|
|
|
|
let text = await this.getTextFromWord(folder, wordFile);
|
2020-06-04 13:44:02 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
// Write VBS file without pragma keywords.
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2024-09-15 14:41:56 -03:00
|
|
|
|
await fs.writeFile(urlJoin(folder, vbsFile), text);
|
2024-08-20 19:12:57 -03:00
|
|
|
|
}
|
2024-03-16 21:36:03 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
// Process node_modules install.
|
2024-03-16 21:36:03 -03:00
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
await this.processNodeModules(folder, min);
|
2024-03-16 21:36:03 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
// Hot swap for .vbs files.
|
2024-03-16 21:36:03 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
const fullFilename = urlJoin(folder, filename);
|
|
|
|
|
if (process.env.DEV_HOTSWAP) {
|
2024-09-07 18:13:36 -03:00
|
|
|
|
watch(fullFilename, async () => {
|
2024-08-20 19:12:57 -03:00
|
|
|
|
await this.translateBASIC(mainName, fullFilename, min);
|
2024-09-07 18:13:36 -03:00
|
|
|
|
const parsedCode: string = await fs.readFile(jsfile, 'utf8');
|
2024-08-20 19:12:57 -03:00
|
|
|
|
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2024-09-15 14:41:56 -03:00
|
|
|
|
const compiledAt = await fs.stat(fullFilename);
|
2024-08-20 19:12:57 -03:00
|
|
|
|
const jsfile = urlJoin(folder, `${filename}.js`);
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
if (await GBUtil.exists(jsfile)) {
|
2024-09-15 14:41:56 -03:00
|
|
|
|
const jsStat = await fs.stat(jsfile);
|
2024-08-21 13:26:40 -03:00
|
|
|
|
const interval = 1000; // If compiled is older 1 seconds, then recompile.
|
2024-08-20 19:12:57 -03:00
|
|
|
|
if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) {
|
|
|
|
|
await this.translateBASIC(mainName, fullFilename, min);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
await this.translateBASIC(mainName, fullFilename, min);
|
2023-02-22 13:18:16 -03:00
|
|
|
|
}
|
2022-11-02 16:03:25 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
// Syncronizes Database Objects with the ones returned from "Word".
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
await this.syncStorageFromTABLE(folder, filename, min, mainName);
|
2024-08-20 19:12:57 -03:00
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
const parsedCode: string = await fs.readFile(jsfile, 'utf8');
|
2024-08-20 19:12:57 -03:00
|
|
|
|
min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode;
|
|
|
|
|
return filename;
|
|
|
|
|
}
|
2024-09-07 18:13:36 -03:00
|
|
|
|
private async processNodeModules(folder: string, min: GBMinInstance) {
|
2023-03-26 19:33:58 -03:00
|
|
|
|
const node_modules = urlJoin(process.env.PWD, folder, 'node_modules');
|
2024-09-15 14:41:56 -03:00
|
|
|
|
if (!(await GBUtil.exists(node_modules))) {
|
2023-02-22 13:18:16 -03:00
|
|
|
|
const packageJson = `
|
2022-11-02 16:03:25 -03:00
|
|
|
|
{
|
|
|
|
|
"name": "${min.botId}.gbdialog",
|
|
|
|
|
"version": "1.0.0",
|
|
|
|
|
"description": "${min.botId} transpiled .gbdialog",
|
|
|
|
|
"author": "${min.botId} owner.",
|
|
|
|
|
"license": "ISC",
|
|
|
|
|
"dependencies": {
|
2024-05-24 14:50:05 -03:00
|
|
|
|
"yaml": "2.4.2",
|
2022-11-02 16:03:25 -03:00
|
|
|
|
"encoding": "0.1.13",
|
|
|
|
|
"isomorphic-fetch": "3.0.0",
|
|
|
|
|
"punycode": "2.1.1",
|
2023-12-01 22:02:37 -03:00
|
|
|
|
"@push-rpc/core": "1.8.2",
|
|
|
|
|
"@push-rpc/http": "1.8.2",
|
2023-12-28 17:19:38 -03:00
|
|
|
|
"vm2": "3.9.11",
|
|
|
|
|
"async-retry": "1.3.3"
|
2022-11-02 16:03:25 -03:00
|
|
|
|
}
|
|
|
|
|
}`;
|
2024-09-15 14:41:56 -03:00
|
|
|
|
await fs.writeFile(urlJoin(folder, 'package.json'), packageJson);
|
2022-11-02 16:03:25 -03:00
|
|
|
|
|
2024-09-12 15:05:32 -03:00
|
|
|
|
GBLogEx.info(min, `Installing node_modules...`);
|
2023-02-22 13:18:16 -03:00
|
|
|
|
const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm');
|
2024-09-07 18:13:36 -03:00
|
|
|
|
child_process.exec(`${npmPath} install`, { cwd: folder });
|
2023-02-22 13:18:16 -03:00
|
|
|
|
}
|
2024-08-20 19:12:57 -03:00
|
|
|
|
}
|
2020-06-14 21:40:41 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
public static async loadConnections(min) {
|
2024-08-29 19:53:56 -03:00
|
|
|
|
// Loads storage custom connections.
|
2024-09-07 00:08:23 -03:00
|
|
|
|
const packagePath = GBUtil.getGBAIPath(min.botId, null);
|
|
|
|
|
const filePath = path.join('work', packagePath, 'connections.json');
|
2024-08-29 19:53:56 -03:00
|
|
|
|
let connections = [];
|
2024-09-07 18:13:36 -03:00
|
|
|
|
if (await GBUtil.exists(filePath)) {
|
|
|
|
|
connections = JSON.parse(await fs.readFile(filePath, 'utf8'));
|
2024-08-29 19:53:56 -03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connections.forEach(async con => {
|
|
|
|
|
const connectionName = con['name'];
|
|
|
|
|
|
|
|
|
|
const dialect = con['storageDriver'];
|
|
|
|
|
const host = con['storageServer'];
|
|
|
|
|
const port = con['storagePort'];
|
|
|
|
|
const storageName = con['storageName'];
|
|
|
|
|
const username = con['storageUsername'];
|
|
|
|
|
const password = con['storagePassword'];
|
|
|
|
|
|
|
|
|
|
const logging: boolean | Function =
|
|
|
|
|
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
|
|
|
|
? (str: string): void => {
|
|
|
|
|
GBLogEx.info(min, str);
|
|
|
|
|
}
|
|
|
|
|
: false;
|
|
|
|
|
|
|
|
|
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
|
|
|
|
const acquire = parseInt(GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT'));
|
|
|
|
|
const sequelizeOptions = {
|
|
|
|
|
define: {
|
|
|
|
|
charset: 'utf8',
|
|
|
|
|
collate: 'utf8_general_ci',
|
|
|
|
|
freezeTableName: true,
|
|
|
|
|
timestamps: false
|
|
|
|
|
},
|
|
|
|
|
host: host,
|
|
|
|
|
port: port,
|
|
|
|
|
logging: logging as boolean,
|
|
|
|
|
dialect: dialect,
|
|
|
|
|
quoteIdentifiers: false, // set case-insensitive
|
|
|
|
|
dialectOptions: {
|
|
|
|
|
options: {
|
|
|
|
|
trustServerCertificate: true,
|
|
|
|
|
encrypt: encrypt,
|
|
|
|
|
requestTimeout: 120 * 1000
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
pool: {
|
|
|
|
|
max: 5,
|
|
|
|
|
min: 0,
|
|
|
|
|
idle: 10000,
|
|
|
|
|
evict: 10000,
|
|
|
|
|
acquire: acquire
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!min[connectionName]) {
|
2024-09-12 15:05:32 -03:00
|
|
|
|
GBLogEx.info(min, `Loading data connection ${connectionName}...`);
|
2024-08-29 19:53:56 -03:00
|
|
|
|
min[connectionName] = new Sequelize(storageName, username, password, sequelizeOptions);
|
|
|
|
|
min[connectionName]['gbconnection'] = con;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
private async syncStorageFromTABLE(folder: string, filename: string, min: GBMinInstance, mainName: string) {
|
2023-10-05 10:06:03 -03:00
|
|
|
|
const tablesFile = urlJoin(folder, `${filename}.tables.json`);
|
2023-10-20 13:39:34 -03:00
|
|
|
|
let sync = false;
|
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
if (await GBUtil.exists(tablesFile)) {
|
2023-10-02 16:22:51 -03:00
|
|
|
|
const minBoot = GBServer.globals.minBoot;
|
2023-10-05 10:06:03 -03:00
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
const tableDef = JSON.parse(await fs.readFile(tablesFile, 'utf8')) as any;
|
2023-10-05 10:06:03 -03:00
|
|
|
|
|
2023-11-29 18:46:02 -03:00
|
|
|
|
const getTypeBasedOnCondition = (t, size) => {
|
|
|
|
|
if (1) {
|
|
|
|
|
switch (t) {
|
|
|
|
|
case 'string':
|
|
|
|
|
return `varchar(${size})`;
|
|
|
|
|
case 'guid':
|
|
|
|
|
return 'UUID';
|
|
|
|
|
case 'key':
|
|
|
|
|
return `varchar(${size})`;
|
|
|
|
|
case 'number':
|
|
|
|
|
return 'BIGINT';
|
|
|
|
|
case 'integer':
|
|
|
|
|
return 'INTEGER';
|
|
|
|
|
case 'double':
|
|
|
|
|
return 'FLOAT';
|
|
|
|
|
case 'float':
|
|
|
|
|
return 'FLOAT';
|
|
|
|
|
case 'date':
|
|
|
|
|
return 'DATE';
|
|
|
|
|
case 'boolean':
|
|
|
|
|
return 'BOOLEAN';
|
|
|
|
|
default:
|
|
|
|
|
return { type: 'TABLE', name: t };
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
switch (t) {
|
|
|
|
|
case 'string':
|
|
|
|
|
return { key: 'STRING' };
|
|
|
|
|
case 'guid':
|
|
|
|
|
return { key: 'UUID' };
|
|
|
|
|
case 'key':
|
|
|
|
|
return { key: 'STRING' }; // Assuming key is a string data type
|
|
|
|
|
case 'number':
|
|
|
|
|
return { key: 'BIGINT' };
|
|
|
|
|
case 'integer':
|
|
|
|
|
return { key: 'INTEGER' };
|
|
|
|
|
case 'double':
|
|
|
|
|
return { key: 'FLOAT' };
|
|
|
|
|
case 'float':
|
|
|
|
|
return { key: 'FLOAT' };
|
|
|
|
|
case 'date':
|
|
|
|
|
return { key: 'DATE' };
|
|
|
|
|
case 'boolean':
|
|
|
|
|
return { key: 'BOOLEAN' };
|
|
|
|
|
default:
|
|
|
|
|
return { key: 'TABLE', name: t };
|
|
|
|
|
}
|
2023-10-05 10:06:03 -03:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-08 16:03:33 -03:00
|
|
|
|
const associations = [];
|
|
|
|
|
|
2024-08-21 13:09:50 -03:00
|
|
|
|
const shouldSync = min.core.getParam<boolean>(min.instance, 'Synchronize Database', false);
|
2023-11-29 18:46:02 -03:00
|
|
|
|
|
2024-08-21 13:09:50 -03:00
|
|
|
|
tableDef.forEach(async t => {
|
2023-11-29 18:46:02 -03:00
|
|
|
|
const tableName = t.name.trim();
|
|
|
|
|
|
2023-11-28 14:13:44 -03:00
|
|
|
|
// Determines autorelationship.
|
2023-10-09 19:21:34 -03:00
|
|
|
|
Object.keys(t.fields).forEach(key => {
|
|
|
|
|
let obj = t.fields[key];
|
2023-11-29 18:46:02 -03:00
|
|
|
|
obj.type = getTypeBasedOnCondition(obj.type, obj.size);
|
2024-08-21 13:09:50 -03:00
|
|
|
|
if (obj.type.key === 'TABLE') {
|
|
|
|
|
obj.type.key = 'BIGINT';
|
2023-11-29 13:20:26 -03:00
|
|
|
|
associations.push({ from: tableName, to: obj.type.name });
|
2023-10-09 19:21:34 -03:00
|
|
|
|
}
|
|
|
|
|
});
|
2023-10-20 13:39:34 -03:00
|
|
|
|
|
2023-11-28 14:13:44 -03:00
|
|
|
|
// Cutom connection for TABLE.
|
2023-11-29 13:20:26 -03:00
|
|
|
|
const connectionName = t.connection;
|
2024-08-26 21:47:57 -03:00
|
|
|
|
let con = min[connectionName];
|
2023-11-28 14:13:44 -03:00
|
|
|
|
|
2023-11-29 18:46:02 -03:00
|
|
|
|
if (!con) {
|
2024-08-31 03:52:37 -03:00
|
|
|
|
GBLogEx.debug(min, `Invalid connection specified: ${min.bot} ${tableName} ${connectionName}.`);
|
|
|
|
|
} else {
|
|
|
|
|
// Field checking, syncs if there is any difference.
|
|
|
|
|
const seq = con ? con : minBoot.core.sequelize;
|
|
|
|
|
|
|
|
|
|
if (seq) {
|
|
|
|
|
const model = seq.models[tableName];
|
|
|
|
|
if (model) {
|
|
|
|
|
// Except Id, checks if has same number of fields.
|
|
|
|
|
let equals = 0;
|
|
|
|
|
Object.keys(t.fields).forEach(key => {
|
|
|
|
|
let obj1 = t.fields[key];
|
|
|
|
|
let obj2 = model['fieldRawAttributesMap'][key];
|
|
|
|
|
|
|
|
|
|
if (key !== 'id') {
|
|
|
|
|
if (obj1 && obj2) {
|
|
|
|
|
equals++;
|
|
|
|
|
}
|
2023-11-29 18:46:02 -03:00
|
|
|
|
}
|
2024-08-31 03:52:37 -03:00
|
|
|
|
});
|
2023-10-20 13:39:34 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
if (equals != Object.keys(t.fields).length) {
|
|
|
|
|
sync = true;
|
|
|
|
|
}
|
2023-11-29 18:46:02 -03:00
|
|
|
|
}
|
2023-10-26 09:51:23 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
seq.define(tableName, t.fields);
|
2023-10-20 17:35:03 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
// New table checking, if needs sync.
|
|
|
|
|
let tables;
|
|
|
|
|
const dialect = con.dialect.name;
|
2023-11-29 00:58:44 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
if (dialect === 'mssql') {
|
|
|
|
|
tables = await seq.query(
|
|
|
|
|
`SELECT table_name, table_schema
|
2023-11-29 18:46:02 -03:00
|
|
|
|
FROM information_schema.tables
|
|
|
|
|
WHERE table_type = 'BASE TABLE'
|
2024-08-21 13:09:50 -03:00
|
|
|
|
ORDER BY table_name ASC`,
|
2024-08-31 03:52:37 -03:00
|
|
|
|
{
|
|
|
|
|
type: QueryTypes.RAW
|
|
|
|
|
}
|
|
|
|
|
)[0];
|
|
|
|
|
} else if (dialect === 'mariadb') {
|
|
|
|
|
tables = await seq.getQueryInterface().showAllTables();
|
2023-11-29 18:46:02 -03:00
|
|
|
|
}
|
2023-10-02 16:22:51 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
let found = false;
|
|
|
|
|
tables.forEach(storageTable => {
|
|
|
|
|
if (storageTable['table_name'] === tableName) {
|
|
|
|
|
found = true;
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-10-08 16:03:33 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
sync = sync ? sync : !found;
|
2023-10-05 10:06:03 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
associations.forEach(e => {
|
|
|
|
|
const from = seq.models[e.from];
|
|
|
|
|
const to = seq.models[e.to];
|
2023-11-29 18:46:02 -03:00
|
|
|
|
|
2024-08-31 03:52:37 -03:00
|
|
|
|
try {
|
|
|
|
|
to.hasMany(from);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`Invalid relationship in ${mainName}: from ${e.from} to ${e.to} (${min.botId})... ${error.message}`
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-11-29 18:46:02 -03:00
|
|
|
|
});
|
2024-08-31 03:52:37 -03:00
|
|
|
|
|
|
|
|
|
if (sync && shouldSync) {
|
|
|
|
|
GBLogEx.info(min, `Syncing changes for TABLE ${connectionName} ${tableName} keyword (${min.botId})...`);
|
|
|
|
|
|
|
|
|
|
await seq.sync({
|
|
|
|
|
alter: true,
|
|
|
|
|
force: false // Keep it false due to data loss danger.
|
|
|
|
|
});
|
|
|
|
|
GBLogEx.info(min, `Done sync for ${min.botId} ${connectionName} ${tableName} storage table...`);
|
|
|
|
|
}
|
2023-11-29 18:46:02 -03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-10-02 16:22:51 -03:00
|
|
|
|
}
|
2019-02-23 13:17:21 -03:00
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 19:36:05 -03:00
|
|
|
|
public async translateBASIC(mainName, filename: any, min: GBMinInstance) {
|
2022-11-02 19:40:59 -03:00
|
|
|
|
// Converts General Bots BASIC into regular VBS
|
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
let basicCode: string = await fs.readFile(filename, 'utf8');
|
2024-09-02 20:16:56 -03:00
|
|
|
|
basicCode = GBVMService.normalizeQuotes(basicCode);
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2024-08-20 19:12:57 -03:00
|
|
|
|
// Pre process SET SCHEDULE calls.
|
|
|
|
|
|
|
|
|
|
const schedules = GBVMService.getSetScheduleKeywordArgs(basicCode);
|
|
|
|
|
|
|
|
|
|
const s = new ScheduleServices();
|
|
|
|
|
await s.deleteScheduleIfAny(min, mainName);
|
|
|
|
|
|
|
|
|
|
let i = 1;
|
2024-08-21 13:09:50 -03:00
|
|
|
|
await CollectionUtil.asyncForEach(schedules, async syntax => {
|
2024-08-20 19:12:57 -03:00
|
|
|
|
if (s) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
await s.createOrUpdateSchedule(min, syntax, `${mainName};${i++}`);
|
2024-08-20 19:12:57 -03:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
basicCode = basicCode.replace(/^\s*SET SCHEDULE (.*)/gim, '');
|
|
|
|
|
|
2022-11-02 19:40:59 -03:00
|
|
|
|
// Process INCLUDE keyword to include another
|
|
|
|
|
// dialog inside the dialog.
|
|
|
|
|
|
|
|
|
|
let include = null;
|
|
|
|
|
do {
|
2022-11-19 23:34:58 -03:00
|
|
|
|
include = /^include\b(.*)$/gim.exec(basicCode);
|
2022-11-02 19:40:59 -03:00
|
|
|
|
|
|
|
|
|
if (include) {
|
|
|
|
|
let includeName = include[1].trim();
|
2024-09-06 15:30:03 -03:00
|
|
|
|
includeName = path.join(path.dirname(filename), includeName);
|
2022-11-19 23:34:58 -03:00
|
|
|
|
includeName = includeName.substr(0, includeName.lastIndexOf('.')) + '.vbs';
|
2022-11-02 19:40:59 -03:00
|
|
|
|
|
|
|
|
|
// To use include, two /publish will be necessary (for now)
|
|
|
|
|
// because of alphabet order may raise not found errors.
|
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
|
let includeCode: string = await fs.readFile(includeName, 'utf8');
|
2022-11-19 23:34:58 -03:00
|
|
|
|
basicCode = basicCode.replace(/^include\b.*$/gim, includeCode);
|
2022-11-02 19:40:59 -03:00
|
|
|
|
}
|
|
|
|
|
} while (include);
|
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
let { code, map, metadata, tasks, systemPrompt } = await this.convert(filename, mainName, basicCode);
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
|
|
|
|
// Generates function JSON metadata to be used later.
|
|
|
|
|
|
|
|
|
|
const jsonFile = `${filename}.json`;
|
2024-09-15 14:41:56 -03:00
|
|
|
|
await fs.writeFile(jsonFile, JSON.stringify(metadata));
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2022-11-12 17:17:14 -03:00
|
|
|
|
const mapFile = `${filename}.map`;
|
2024-09-15 14:41:56 -03:00
|
|
|
|
await fs.writeFile(mapFile, JSON.stringify(map));
|
2022-11-02 19:40:59 -03:00
|
|
|
|
|
2023-09-30 20:43:39 -03:00
|
|
|
|
// Execute off-line code tasks
|
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
await this.executeTasks(min, tasks);
|
2023-09-30 20:43:39 -03:00
|
|
|
|
|
2022-11-02 19:40:59 -03:00
|
|
|
|
// Run JS into the GB context.
|
|
|
|
|
|
2023-01-29 12:02:14 -03:00
|
|
|
|
const jsfile: string = `${filename}.js`;
|
2022-11-02 19:40:59 -03:00
|
|
|
|
|
2024-09-15 16:30:03 -03:00
|
|
|
|
const template = (await fs.readFile('./vm-inject.js')).toString();
|
|
|
|
|
code = template.replace('//##INJECTED_CODE_HERE', code );
|
|
|
|
|
code = template.replace('//##INJECTED_HEADER', `port=${GBVMService.API_PORT}; botId='${min.botId}';` );
|
2023-12-29 21:43:48 -03:00
|
|
|
|
|
|
|
|
|
code = ji.default(code, ' ');
|
|
|
|
|
|
2024-09-15 14:41:56 -03:00
|
|
|
|
await fs.writeFile(jsfile, code);
|
2024-09-12 15:05:32 -03:00
|
|
|
|
GBLogEx.info(min, `Code reloaded: ${path.basename(filename)}.`);
|
2023-09-30 20:43:39 -03:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
private async executeTasks(min, tasks) {
|
2023-09-30 20:43:39 -03:00
|
|
|
|
for (let i = 0; i < tasks.length; i++) {
|
|
|
|
|
const task = tasks[i];
|
|
|
|
|
|
2023-10-02 16:22:51 -03:00
|
|
|
|
if (task.kind === 'writeTableDefinition') {
|
|
|
|
|
// Creates an empty object that will receive Sequelize fields.
|
2023-09-30 20:43:39 -03:00
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
const tablesFile = `${task.file}.tables.json`;
|
2024-09-15 14:41:56 -03:00
|
|
|
|
await fs.writeFile(tablesFile, JSON.stringify(task.tables));
|
2023-09-30 20:43:39 -03:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-02 19:40:59 -03:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 16:09:45 -03:00
|
|
|
|
public static getMethodNameFromVBSFilename(filename: string) {
|
2023-01-04 16:26:18 -03:00
|
|
|
|
let mainName = filename.replace(/\s*|\-/gim, '').split('.')[0];
|
2020-11-06 17:06:22 -03:00
|
|
|
|
return mainName.toLowerCase();
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-16 21:36:03 -03:00
|
|
|
|
public static getSetScheduleKeywordArgs(code) {
|
|
|
|
|
if (!code) return [];
|
|
|
|
|
|
|
|
|
|
const lines = code.split(/\n/);
|
|
|
|
|
const results = [];
|
|
|
|
|
|
|
|
|
|
lines.forEach(line => {
|
|
|
|
|
if (line.trim()) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
const keyword = /^\s*SET SCHEDULE (.*)/gi;
|
2024-03-16 21:36:03 -03:00
|
|
|
|
let result: any = keyword.exec(line);
|
|
|
|
|
if (result) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
result = result[1].replace(/\`|\"|\'/, '');
|
2024-03-16 21:36:03 -03:00
|
|
|
|
result = result.trim();
|
|
|
|
|
results.push(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-08-09 17:55:55 -03:00
|
|
|
|
|
2024-03-16 21:36:03 -03:00
|
|
|
|
return results;
|
|
|
|
|
}
|
2024-08-21 13:09:50 -03:00
|
|
|
|
|
2023-01-13 16:09:45 -03:00
|
|
|
|
private async getTextFromWord(folder: string, filename: string) {
|
2020-05-15 14:07:30 -03:00
|
|
|
|
return new Promise<string>(async (resolve, reject) => {
|
2024-09-07 00:08:23 -03:00
|
|
|
|
const filePath = urlJoin(folder, filename);
|
2024-09-07 18:13:36 -03:00
|
|
|
|
textract.fromFileWithPath(filePath, { preserveLineBreaks: true }, async (error, text) => {
|
2020-08-29 15:02:19 -03:00
|
|
|
|
if (error) {
|
2023-02-22 13:18:16 -03:00
|
|
|
|
if (error.message.startsWith('File not correctly recognized as zip file')) {
|
2024-09-07 18:13:36 -03:00
|
|
|
|
text = await fs.readFile(filePath, 'utf8');
|
2023-02-22 13:18:16 -03:00
|
|
|
|
} else {
|
|
|
|
|
reject(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resolve(text);
|
2020-08-29 15:02:19 -03:00
|
|
|
|
});
|
2020-05-15 14:07:30 -03:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-23 08:11:09 -03:00
|
|
|
|
public static normalizeQuotes(text: any) {
|
2023-11-29 19:06:41 -03:00
|
|
|
|
text = text.replace(/\"/gm, '`');
|
|
|
|
|
text = text.replace(/\¨/gm, '`');
|
|
|
|
|
text = text.replace(/\“/gm, '`');
|
|
|
|
|
text = text.replace(/\”/gm, '`');
|
2023-03-19 20:09:54 -03:00
|
|
|
|
text = text.replace(/\‘/gm, "'");
|
|
|
|
|
text = text.replace(/\’/gm, "'");
|
2023-03-26 19:33:58 -03:00
|
|
|
|
|
2023-02-23 08:11:09 -03:00
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-02 20:16:56 -03:00
|
|
|
|
public static getMetadata(mainName: string, propertiesText: string[][], description: string) {
|
2024-03-06 14:38:37 -03:00
|
|
|
|
let properties = {};
|
|
|
|
|
if (!propertiesText || !description) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
return {};
|
2024-03-04 20:05:56 -03:00
|
|
|
|
}
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2024-09-02 20:16:56 -03:00
|
|
|
|
const getType = (asClause: string) => {
|
2024-03-06 14:38:37 -03:00
|
|
|
|
asClause = asClause.trim().toUpperCase();
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2024-03-06 14:38:37 -03:00
|
|
|
|
if (asClause.indexOf('STRING') !== -1) {
|
2024-03-04 20:05:56 -03:00
|
|
|
|
return 'string';
|
2024-08-21 13:09:50 -03:00
|
|
|
|
} else if (asClause.indexOf('OBJECT') !== -1) {
|
2024-03-04 20:05:56 -03:00
|
|
|
|
return 'object';
|
2024-08-21 13:09:50 -03:00
|
|
|
|
} else if (asClause.indexOf('INTEGER') !== -1 || asClause.indexOf('NUMBER') !== -1) {
|
2024-03-04 20:05:56 -03:00
|
|
|
|
return 'number';
|
|
|
|
|
} else {
|
|
|
|
|
return 'enum';
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2024-03-04 20:05:56 -03:00
|
|
|
|
for (let i = 0; i < propertiesText.length; i++) {
|
|
|
|
|
const propertiesExp = propertiesText[i];
|
|
|
|
|
const t = getType(propertiesExp[2]);
|
|
|
|
|
let element;
|
2024-09-15 14:41:56 -03:00
|
|
|
|
const description = propertiesExp[4]?.trim();
|
|
|
|
|
|
2024-03-04 20:05:56 -03:00
|
|
|
|
if (t === 'enum') {
|
2024-09-02 20:16:56 -03:00
|
|
|
|
const list = propertiesExp[2] as any;
|
|
|
|
|
element = z.enum(list.split(','));
|
2024-03-04 20:05:56 -03:00
|
|
|
|
} else if (t === 'string') {
|
2024-09-15 14:41:56 -03:00
|
|
|
|
element = z.string({ description: description });
|
2024-03-04 20:05:56 -03:00
|
|
|
|
} else if (t === 'object') {
|
2024-09-15 14:41:56 -03:00
|
|
|
|
element = z.string({ description: description }); // Assuming 'object' is represented as a string here
|
2024-03-04 20:05:56 -03:00
|
|
|
|
} else if (t === 'number') {
|
2024-09-15 14:41:56 -03:00
|
|
|
|
element = z.number({ description: description });
|
2024-03-06 14:38:37 -03:00
|
|
|
|
} else {
|
|
|
|
|
GBLog.warn(`Element type invalid specified on .docx: ${propertiesExp[0]}`);
|
2023-09-19 19:36:05 -03:00
|
|
|
|
}
|
2024-09-04 00:18:19 -03:00
|
|
|
|
|
2024-03-04 20:05:56 -03:00
|
|
|
|
element['type'] = t;
|
2024-03-06 14:38:37 -03:00
|
|
|
|
properties[propertiesExp[1].trim()] = element;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
}
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2024-09-02 20:16:56 -03:00
|
|
|
|
const json = {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
type: 'function',
|
2024-03-04 20:05:56 -03:00
|
|
|
|
function: {
|
2024-09-02 20:16:56 -03:00
|
|
|
|
name: mainName,
|
2024-03-13 20:26:13 -03:00
|
|
|
|
description: description ? description : '',
|
2024-09-04 00:18:19 -03:00
|
|
|
|
schema: zodToJsonSchema(z.object(properties))
|
2024-09-02 20:16:56 -03:00
|
|
|
|
},
|
|
|
|
|
arguments: propertiesText.reduce((acc, prop) => {
|
2024-09-15 14:41:56 -03:00
|
|
|
|
acc[prop[1].trim()] = prop[3]?.trim(); // Assuming value is in the 3rd index
|
2024-09-02 20:16:56 -03:00
|
|
|
|
return acc;
|
|
|
|
|
}, {})
|
2024-08-21 13:09:50 -03:00
|
|
|
|
};
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2023-09-19 19:36:05 -03:00
|
|
|
|
return json;
|
|
|
|
|
}
|
2024-09-15 14:41:56 -03:00
|
|
|
|
|
2023-09-30 20:43:39 -03:00
|
|
|
|
public async parseField(line) {
|
|
|
|
|
let required = line.indexOf('*') !== -1;
|
2024-01-06 19:33:21 -03:00
|
|
|
|
let unique = /\bunique\b/gi.test(line);
|
2024-03-04 20:05:56 -03:00
|
|
|
|
let primaryKey = /\bkey\b/gi.test(line);
|
|
|
|
|
let autoIncrement = /\bauto\b/gi.test(line);
|
2024-01-14 22:23:53 -03:00
|
|
|
|
|
2024-03-04 20:05:56 -03:00
|
|
|
|
if (primaryKey) {
|
2024-01-14 22:23:53 -03:00
|
|
|
|
autoIncrement = true;
|
|
|
|
|
unique = true;
|
|
|
|
|
required = true;
|
|
|
|
|
}
|
2024-03-04 20:05:56 -03:00
|
|
|
|
|
2023-09-30 20:43:39 -03:00
|
|
|
|
line = line.replace('*', '');
|
|
|
|
|
|
2023-10-05 11:28:23 -03:00
|
|
|
|
const fieldRegExp = /^\s*(\w+)\s*(\w+)(?:\((.*)\))?/gim;
|
2023-09-30 20:43:39 -03:00
|
|
|
|
|
2023-10-02 16:22:51 -03:00
|
|
|
|
let reg = fieldRegExp.exec(line);
|
2023-10-05 10:06:03 -03:00
|
|
|
|
const name = reg[1];
|
2023-11-29 13:20:26 -03:00
|
|
|
|
const t = reg[2];
|
2023-10-05 10:06:03 -03:00
|
|
|
|
|
2024-03-04 20:05:56 -03:00
|
|
|
|
let definition = {
|
|
|
|
|
allowNull: !required,
|
2024-08-21 13:09:50 -03:00
|
|
|
|
unique: unique,
|
|
|
|
|
primaryKey: primaryKey,
|
2024-03-04 20:05:56 -03:00
|
|
|
|
autoIncrement: autoIncrement
|
|
|
|
|
};
|
2023-10-05 10:06:03 -03:00
|
|
|
|
definition['type'] = t;
|
|
|
|
|
|
|
|
|
|
if (reg[3]) {
|
2023-11-29 18:46:02 -03:00
|
|
|
|
definition['size'] = Number.parseInt(reg[3] === 'max' ? '4000' : reg[3]);
|
2023-09-30 20:43:39 -03:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
return { name, definition };
|
2023-09-30 20:43:39 -03:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-23 13:17:21 -03:00
|
|
|
|
/**
|
|
|
|
|
* Converts General Bots BASIC
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @param code General Bots BASIC
|
|
|
|
|
*/
|
2023-10-05 10:06:03 -03:00
|
|
|
|
public async convert(filename: string, mainName: string, code: string) {
|
2022-11-02 16:03:25 -03:00
|
|
|
|
// Start and End of VB2TS tags of processing.
|
2020-11-22 11:22:55 -03:00
|
|
|
|
|
2023-02-12 14:31:21 -03:00
|
|
|
|
code = process.env.ENABLE_AUTH ? `hear GBLogExin as login\n${code}` : code;
|
2023-01-29 17:20:38 -03:00
|
|
|
|
var lines = code.split('\n');
|
2023-02-04 10:45:30 -03:00
|
|
|
|
const keywords = KeywordsExpressions.getKeywords();
|
2023-01-29 17:20:38 -03:00
|
|
|
|
let current = 41;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
const map = {};
|
|
|
|
|
let properties = [];
|
|
|
|
|
let description;
|
2023-09-30 20:43:39 -03:00
|
|
|
|
let table = null; // Used for TABLE keyword.
|
2024-02-18 01:15:47 -03:00
|
|
|
|
let talk = null;
|
2024-03-11 13:30:11 -03:00
|
|
|
|
let systemPrompt = null;
|
2023-11-29 00:58:44 -03:00
|
|
|
|
let connection = null;
|
2023-09-30 20:43:39 -03:00
|
|
|
|
const tasks = [];
|
2023-10-05 10:06:03 -03:00
|
|
|
|
let fields = {};
|
2023-10-09 19:21:34 -03:00
|
|
|
|
let tables = [];
|
2022-11-04 14:28:02 -03:00
|
|
|
|
|
2023-12-29 21:43:48 -03:00
|
|
|
|
const outputLines = [];
|
|
|
|
|
let emmitIndex = 1;
|
2023-01-29 17:20:38 -03:00
|
|
|
|
for (let i = 1; i <= lines.length; i++) {
|
2023-04-09 19:20:15 -03:00
|
|
|
|
let line = lines[i - 1];
|
|
|
|
|
|
2023-12-12 13:47:07 -03:00
|
|
|
|
// Remove lines before statements.
|
2023-04-09 19:20:15 -03:00
|
|
|
|
|
2023-09-19 19:36:05 -03:00
|
|
|
|
line = line.replace(/^\s*\d+\s*/gi, '');
|
2023-04-09 19:20:15 -03:00
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
if (!table && !talk && !systemPrompt) {
|
2023-12-11 22:13:36 -03:00
|
|
|
|
for (let j = 0; j < keywords.length; j++) {
|
|
|
|
|
line = line.replace(keywords[j][0], keywords[j][1]); // TODO: Investigate delay here.
|
|
|
|
|
}
|
2023-01-29 17:20:38 -03:00
|
|
|
|
}
|
2022-11-04 14:28:02 -03:00
|
|
|
|
|
2023-09-30 20:43:39 -03:00
|
|
|
|
// Pre-process "off-line" static KEYWORDS.
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
2023-09-30 20:43:39 -03:00
|
|
|
|
let emmit = true;
|
2024-09-02 20:16:56 -03:00
|
|
|
|
const params = /^\s*PARAM\s*(.*)\s*AS\s*(.*)\s*LIKE\s*(.*)\s*DESCRIPTION\s*(.*)/gim;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
const param = params.exec(line);
|
|
|
|
|
if (param) {
|
|
|
|
|
properties.push(param);
|
2023-09-30 20:43:39 -03:00
|
|
|
|
emmit = false;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 14:38:37 -03:00
|
|
|
|
const descriptionKeyword = /^\s*DESCRIPTION\s(.*)/gim;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
let descriptionReg = descriptionKeyword.exec(line);
|
|
|
|
|
if (descriptionReg) {
|
|
|
|
|
description = descriptionReg[1];
|
2023-09-30 20:43:39 -03:00
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
const endSystemPromptKeyword = /^\s*END SYSTEM PROMPT\s*/gim;
|
|
|
|
|
let endSystemPromptReg = endSystemPromptKeyword.exec(line);
|
|
|
|
|
if (endSystemPromptReg && systemPrompt) {
|
|
|
|
|
line = systemPrompt + '`})';
|
2024-03-13 20:26:13 -03:00
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
systemPrompt = null;
|
|
|
|
|
emmit = true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-18 01:15:47 -03:00
|
|
|
|
const endTalkKeyword = /^\s*END TALK\s*/gim;
|
|
|
|
|
let endTalkReg = endTalkKeyword.exec(line);
|
|
|
|
|
if (endTalkReg && talk) {
|
|
|
|
|
line = talk + '`})';
|
2024-03-04 20:05:56 -03:00
|
|
|
|
|
2024-02-18 01:15:47 -03:00
|
|
|
|
talk = null;
|
|
|
|
|
emmit = true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
const endTableKeyword = /^\s*END TABLE\s*/gim;
|
2023-09-30 20:43:39 -03:00
|
|
|
|
let endTableReg = endTableKeyword.exec(line);
|
2023-10-05 10:06:03 -03:00
|
|
|
|
if (endTableReg && table) {
|
2023-10-09 19:21:34 -03:00
|
|
|
|
tables.push({
|
2024-08-21 13:09:50 -03:00
|
|
|
|
name: table,
|
|
|
|
|
fields: fields,
|
|
|
|
|
connection: connection
|
2023-09-30 20:43:39 -03:00
|
|
|
|
});
|
|
|
|
|
|
2023-10-20 13:39:34 -03:00
|
|
|
|
fields = {};
|
2023-09-30 20:43:39 -03:00
|
|
|
|
table = null;
|
2023-11-29 00:58:44 -03:00
|
|
|
|
connection = null;
|
2023-09-30 20:43:39 -03:00
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-18 01:15:47 -03:00
|
|
|
|
// Inside BEGIN TALK
|
|
|
|
|
|
|
|
|
|
if (talk) {
|
|
|
|
|
talk += line + '\\n';
|
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
// Inside BEGIN SYSTEM PROMPT
|
|
|
|
|
|
|
|
|
|
if (systemPrompt) {
|
|
|
|
|
systemPrompt += line + '\\n';
|
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
// Inside BEGIN/END table pair containing FIELDS.
|
2023-09-30 20:43:39 -03:00
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
if (table && line.trim() !== '') {
|
|
|
|
|
const field = await this.parseField(line);
|
2023-11-29 13:20:26 -03:00
|
|
|
|
fields[field['name']] = field.definition;
|
2023-10-05 10:06:03 -03:00
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
2023-09-30 20:43:39 -03:00
|
|
|
|
|
2023-11-29 00:58:44 -03:00
|
|
|
|
const tableKeyword = /^\s*TABLE\s*(.*)\s*ON\s*(.*)/gim;
|
2023-10-05 10:06:03 -03:00
|
|
|
|
let tableReg = tableKeyword.exec(line);
|
|
|
|
|
if (tableReg && !table) {
|
|
|
|
|
table = tableReg[1];
|
2023-11-29 18:46:02 -03:00
|
|
|
|
connection = tableReg[2];
|
2023-10-05 10:06:03 -03:00
|
|
|
|
emmit = false;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
}
|
2023-10-05 10:06:03 -03:00
|
|
|
|
|
2024-02-18 01:15:47 -03:00
|
|
|
|
const talkKeyword = /^\s*BEGIN TALK\s*/gim;
|
|
|
|
|
let talkReg = talkKeyword.exec(line);
|
|
|
|
|
if (talkReg && !talk) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
talk = 'await dk.talk ({pid: pid, text: `';
|
2024-02-18 01:15:47 -03:00
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
const systemPromptKeyword = /^\s*BEGIN SYSTEM PROMPT\s*/gim;
|
|
|
|
|
let systemPromptReg = systemPromptKeyword.exec(line);
|
|
|
|
|
if (systemPromptReg && !systemPrompt) {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
systemPrompt = 'await sys.setSystemPrompt ({pid: pid, text: `';
|
2024-03-11 13:30:11 -03:00
|
|
|
|
emmit = false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-05 10:06:03 -03:00
|
|
|
|
// Add additional lines returned from replacement.
|
|
|
|
|
|
|
|
|
|
let add = emmit ? line.split(/\r\n|\r|\n/).length : 0;
|
|
|
|
|
current = current + (add ? add : 0);
|
2023-12-29 21:43:48 -03:00
|
|
|
|
|
2024-03-04 20:05:56 -03:00
|
|
|
|
if (emmit) {
|
|
|
|
|
emmitIndex++;
|
2023-12-29 21:43:48 -03:00
|
|
|
|
map[emmitIndex] = current;
|
|
|
|
|
outputLines[emmitIndex - 1] = line;
|
|
|
|
|
}
|
2022-11-12 17:17:14 -03:00
|
|
|
|
}
|
2022-11-11 21:35:05 -03:00
|
|
|
|
|
2023-10-20 13:39:34 -03:00
|
|
|
|
if (tables) {
|
2023-10-09 19:21:34 -03:00
|
|
|
|
tasks.push({
|
2024-08-21 13:09:50 -03:00
|
|
|
|
kind: 'writeTableDefinition',
|
|
|
|
|
file: filename,
|
|
|
|
|
tables
|
2023-10-09 19:21:34 -03:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-29 21:43:48 -03:00
|
|
|
|
code = `${outputLines.join('\n')}\n`;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
|
|
|
|
|
let metadata = GBVMService.getMetadata(mainName, properties, description);
|
|
|
|
|
|
2024-03-11 13:30:11 -03:00
|
|
|
|
return { code, map, metadata, tasks, systemPrompt };
|
2022-11-11 21:35:05 -03:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-05 07:47:48 -03:00
|
|
|
|
/**
|
|
|
|
|
* Executes the converted JavaScript from BASIC code inside execution context.
|
|
|
|
|
*/
|
2024-08-21 13:09:50 -03:00
|
|
|
|
public static async callVM(text: string, min: GBMinInstance, step, pid, debug: boolean = false, params = []) {
|
2021-01-05 07:47:48 -03:00
|
|
|
|
// Creates a class DialogKeywords which is the *this* pointer
|
|
|
|
|
// in BASIC.
|
2021-08-09 21:47:36 -03:00
|
|
|
|
|
2023-01-13 16:09:45 -03:00
|
|
|
|
const sandbox = {};
|
2022-06-06 18:03:02 -03:00
|
|
|
|
const contentLocale = min.core.getParam<string>(
|
|
|
|
|
min.instance,
|
|
|
|
|
'Default Content Language',
|
|
|
|
|
GBConfigService.get('DEFAULT_CONTENT_LANGUAGE')
|
|
|
|
|
);
|
|
|
|
|
|
2024-09-04 00:18:19 -03:00
|
|
|
|
let variables = {};
|
2023-10-04 15:30:29 -03:00
|
|
|
|
|
2023-11-17 14:27:12 -03:00
|
|
|
|
// These variables will be automatically be available as normal BASIC variables.
|
|
|
|
|
|
2023-11-02 13:31:46 -03:00
|
|
|
|
try {
|
2024-08-21 13:09:50 -03:00
|
|
|
|
variables['aadToken'] = await (min.adminService as any)['acquireElevatedToken'](min.instance.instanceId, false);
|
2023-11-02 13:31:46 -03:00
|
|
|
|
} catch (error) {
|
|
|
|
|
variables['aadToken'] = 'ERROR: Configure /setupSecurity before using aadToken variable.';
|
2023-11-17 14:27:12 -03:00
|
|
|
|
}
|
2023-10-04 15:39:03 -03:00
|
|
|
|
|
2023-10-04 15:30:29 -03:00
|
|
|
|
// Adds all .gbot params as variables.
|
2023-10-05 10:06:03 -03:00
|
|
|
|
|
2023-10-04 15:30:29 -03:00
|
|
|
|
const gbotConfig = JSON.parse(min.instance.params);
|
|
|
|
|
let keys = Object.keys(gbotConfig);
|
|
|
|
|
for (let j = 0; j < keys.length; j++) {
|
2023-11-29 13:20:26 -03:00
|
|
|
|
const v = keys[j].replace(/\s/gi, '');
|
|
|
|
|
variables[v] = gbotConfig[keys[j]];
|
2023-10-04 15:30:29 -03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Auto-NLP generates BASIC variables related to entities.
|
|
|
|
|
|
2023-02-27 19:17:52 -03:00
|
|
|
|
if (step ? step.context.activity.originalText : null && min['nerEngine']) {
|
|
|
|
|
const result = await min['nerEngine'].process(step.context.activity.originalText);
|
2022-06-07 18:37:29 -03:00
|
|
|
|
|
2023-02-27 14:34:38 -03:00
|
|
|
|
for (let i = 0; i < result.entities.length; i++) {
|
|
|
|
|
const v = result.entities[i];
|
|
|
|
|
const variableName = `${v.entity}`;
|
2023-02-27 19:17:52 -03:00
|
|
|
|
variables[variableName] = v.option ? v.option : v.sourceText;
|
2023-02-27 14:34:38 -03:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-06 18:03:02 -03:00
|
|
|
|
|
2023-12-15 11:59:24 -03:00
|
|
|
|
// Adds params as variables to be added later as global objects.
|
2023-09-17 21:40:34 -03:00
|
|
|
|
|
2023-10-04 15:30:29 -03:00
|
|
|
|
keys = Object.keys(params);
|
2023-09-17 21:40:34 -03:00
|
|
|
|
for (let j = 0; j < keys.length; j++) {
|
2023-09-19 19:36:05 -03:00
|
|
|
|
variables[keys[j]] = params[keys[j]];
|
2023-09-17 21:40:34 -03:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 23:17:35 -03:00
|
|
|
|
const botId = min.botId;
|
2024-09-07 00:08:23 -03:00
|
|
|
|
const packagePath = GBUtil.getGBAIPath(min.botId, `gbdialog`);
|
|
|
|
|
const gbdialogPath = urlJoin(process.cwd(), 'work', packagePath);
|
2024-09-04 00:18:19 -03:00
|
|
|
|
const scriptFilePath = urlJoin(gbdialogPath, `${text}.js`);
|
2021-01-13 13:36:44 -03:00
|
|
|
|
|
2022-10-22 13:23:32 -03:00
|
|
|
|
let code = min.sandBoxMap[text];
|
2023-09-19 19:36:05 -03:00
|
|
|
|
const channel = step ? step.context.activity.channelId : 'web';
|
2024-03-04 20:05:56 -03:00
|
|
|
|
|
2023-03-04 16:27:25 -03:00
|
|
|
|
const dk = new DialogKeywords();
|
|
|
|
|
const sys = new SystemKeywords();
|
2023-09-19 19:36:05 -03:00
|
|
|
|
await dk.setFilter({ pid: pid, value: null });
|
|
|
|
|
|
2023-12-10 12:21:28 -03:00
|
|
|
|
// Find all tokens in .gbot Config.
|
2024-03-04 20:05:56 -03:00
|
|
|
|
|
2023-12-10 12:21:28 -03:00
|
|
|
|
const strFind = ' Client ID';
|
|
|
|
|
const tokens = await min.core['findParam'](min.instance, strFind);
|
2023-12-10 20:24:48 -03:00
|
|
|
|
let tokensList = [];
|
2023-12-10 12:21:28 -03:00
|
|
|
|
await CollectionUtil.asyncForEach(tokens, async t => {
|
2023-12-25 17:47:23 -03:00
|
|
|
|
const tokenName = t.replace(strFind, '');
|
|
|
|
|
tokensList.push(tokenName);
|
2023-12-10 12:21:28 -03:00
|
|
|
|
});
|
|
|
|
|
|
2023-12-10 20:24:48 -03:00
|
|
|
|
sandbox['tokens'] = tokensList.join(',');
|
2023-02-27 19:17:52 -03:00
|
|
|
|
sandbox['variables'] = variables;
|
2023-03-04 16:27:25 -03:00
|
|
|
|
sandbox['id'] = sys.getRandomId();
|
2023-02-16 10:27:18 -03:00
|
|
|
|
sandbox['username'] = await dk.userName({ pid });
|
|
|
|
|
sandbox['mobile'] = await dk.userMobile({ pid });
|
|
|
|
|
sandbox['from'] = await dk.userMobile({ pid });
|
2023-01-13 16:09:45 -03:00
|
|
|
|
sandbox['ENTER'] = String.fromCharCode(13);
|
|
|
|
|
sandbox['headers'] = {};
|
|
|
|
|
sandbox['httpUsername'] = '';
|
|
|
|
|
sandbox['httpPs'] = '';
|
|
|
|
|
sandbox['pid'] = pid;
|
2023-03-02 14:24:51 -03:00
|
|
|
|
sandbox['contentLocale'] = contentLocale;
|
2023-09-19 19:36:05 -03:00
|
|
|
|
sandbox['callTimeout'] = 60 * 60 * 24 * 1000;
|
2023-03-26 19:33:58 -03:00
|
|
|
|
sandbox['channel'] = channel;
|
2023-03-27 17:38:31 -03:00
|
|
|
|
sandbox['today'] = await dk.getToday({ pid });
|
|
|
|
|
sandbox['now'] = await dk.getNow({ pid });
|
2024-03-13 20:26:13 -03:00
|
|
|
|
sandbox['returnValue'] = null;
|
2023-02-16 10:27:18 -03:00
|
|
|
|
let result;
|
|
|
|
|
|
|
|
|
|
try {
|
2024-08-28 19:42:12 -03:00
|
|
|
|
if (!GBConfigService.get('GBVM')) {
|
2024-03-13 20:26:13 -03:00
|
|
|
|
return await (async () => {
|
2024-03-15 07:14:21 -03:00
|
|
|
|
return await new Promise((resolve, reject) => {
|
2024-03-13 20:26:13 -03:00
|
|
|
|
sandbox['resolve'] = resolve;
|
2024-04-01 11:55:45 -03:00
|
|
|
|
// TODO: #411 sandbox['reject'] = reject;
|
2024-08-21 13:09:50 -03:00
|
|
|
|
sandbox['reject'] = () => {};
|
2024-04-01 11:55:45 -03:00
|
|
|
|
|
2024-03-13 20:26:13 -03:00
|
|
|
|
const vm1 = new NodeVM({
|
|
|
|
|
allowAsync: true,
|
|
|
|
|
sandbox: sandbox,
|
|
|
|
|
console: 'inherit',
|
|
|
|
|
wrapper: 'commonjs',
|
|
|
|
|
require: {
|
|
|
|
|
builtin: ['stream', 'http', 'https', 'url', 'zlib', 'net', 'tls', 'crypto'],
|
|
|
|
|
root: ['./'],
|
|
|
|
|
external: true,
|
|
|
|
|
context: 'sandbox'
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-09-04 00:18:19 -03:00
|
|
|
|
const s = new VMScript(code, { filename: scriptFilePath });
|
2024-03-13 20:26:13 -03:00
|
|
|
|
result = vm1.run(s);
|
|
|
|
|
});
|
|
|
|
|
})();
|
2023-02-16 10:27:18 -03:00
|
|
|
|
} else {
|
|
|
|
|
const runnerPath = urlJoin(
|
|
|
|
|
process.cwd(),
|
|
|
|
|
'dist',
|
|
|
|
|
'packages',
|
|
|
|
|
'basic.gblib',
|
|
|
|
|
'services',
|
|
|
|
|
'vm2-process',
|
|
|
|
|
'vm2ProcessRunner.js'
|
|
|
|
|
);
|
|
|
|
|
|
2022-11-12 21:33:45 -03:00
|
|
|
|
const { run } = createVm2Pool({
|
|
|
|
|
min: 0,
|
|
|
|
|
max: 0,
|
2022-11-13 22:56:09 -03:00
|
|
|
|
debug: debug,
|
2024-09-04 00:18:19 -03:00
|
|
|
|
// debuggerport: GBVMService.DEBUGGER_PORT,
|
2022-11-11 21:35:05 -03:00
|
|
|
|
botId: botId,
|
2022-10-28 23:17:35 -03:00
|
|
|
|
cpu: 100,
|
2022-11-02 16:03:25 -03:00
|
|
|
|
memory: 50000,
|
|
|
|
|
time: 60 * 60 * 24 * 14,
|
2024-09-04 00:18:19 -03:00
|
|
|
|
cwd: gbdialogPath,
|
2022-10-28 23:17:35 -03:00
|
|
|
|
script: runnerPath
|
|
|
|
|
});
|
|
|
|
|
|
2024-09-15 14:41:56 -03:00
|
|
|
|
result = await run(code, Object.assign(sandbox, { filename: scriptFilePath }));
|
2023-02-16 10:27:18 -03:00
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
throw new Error(`BASIC RUNTIME ERR: ${error.message ? error.message : error}\n Stack:${error.stack}`);
|
2020-12-06 16:22:34 -03:00
|
|
|
|
}
|
2020-08-29 15:02:19 -03:00
|
|
|
|
}
|
2023-08-21 13:21:49 -03:00
|
|
|
|
|
2024-08-21 13:09:50 -03:00
|
|
|
|
public static createProcessInfo(
|
|
|
|
|
user: GuaribasUser,
|
|
|
|
|
min: GBMinInstance,
|
|
|
|
|
channel: any,
|
|
|
|
|
executable: string,
|
|
|
|
|
step = null
|
|
|
|
|
) {
|
2023-08-21 13:21:49 -03:00
|
|
|
|
const pid = GBAdminService.getNumberIdentifier();
|
|
|
|
|
GBServer.globals.processes[pid] = {
|
|
|
|
|
pid: pid,
|
|
|
|
|
userId: user ? user.userId : 0,
|
|
|
|
|
instanceId: min.instance.instanceId,
|
2023-08-23 11:24:48 -03:00
|
|
|
|
channel: channel,
|
2023-10-05 10:06:03 -03:00
|
|
|
|
roles: 'everyone',
|
2024-03-16 21:36:03 -03:00
|
|
|
|
step: step,
|
2023-10-05 10:06:03 -03:00
|
|
|
|
executable: executable
|
2023-08-21 13:21:49 -03:00
|
|
|
|
};
|
|
|
|
|
return pid;
|
|
|
|
|
}
|
2018-11-12 12:20:44 -02:00
|
|
|
|
}
|