new(basic.gblib): API online for GB.
This commit is contained in:
parent
f520c69f3f
commit
adac385b5a
13 changed files with 3168 additions and 164 deletions
14
api-template.json
Normal file
14
api-template.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "General Bots API",
|
||||
"description": "General Bots API description in Swagger format",
|
||||
"version": "1.0"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://gb.pragmatismo.com.br/api",
|
||||
"description": "General Bots Online"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -74,6 +74,7 @@
|
|||
"@nosferatu500/textract": "3.1.2",
|
||||
"@push-rpc/core": "1.8.2",
|
||||
"@push-rpc/http": "1.8.2",
|
||||
"@push-rpc/openapi": "^1.9.0",
|
||||
"@push-rpc/websocket": "1.8.2",
|
||||
"@semantic-release/changelog": "5.0.1",
|
||||
"@semantic-release/exec": "5.0.0",
|
||||
|
@ -176,6 +177,7 @@
|
|||
"ssr-for-bots": "1.0.1-c",
|
||||
"strict-password-generator": "1.1.2",
|
||||
"swagger-client": "3.18.5",
|
||||
"swagger-ui-dist": "^5.11.0",
|
||||
"tabulator-tables": "5.4.2",
|
||||
"tedious": "15.1.2",
|
||||
"textract": "2.5.0",
|
||||
|
|
|
@ -43,96 +43,6 @@ import { CodeServices } from '../../gpt.gblib/services/CodeServices.js';
|
|||
* Web Automation services of conversation to be called by BASIC.
|
||||
*/
|
||||
export class DebuggerService {
|
||||
static systemVariables = [
|
||||
'AggregateError',
|
||||
'Array',
|
||||
'ArrayBuffer',
|
||||
'Atomics',
|
||||
'BigInt',
|
||||
'BigInt64Array',
|
||||
'BigUint64Array',
|
||||
'Boolean',
|
||||
'DataView',
|
||||
'Date',
|
||||
'Error',
|
||||
'EvalError',
|
||||
'FinalizationRegistry',
|
||||
'Float32Array',
|
||||
'Float64Array',
|
||||
'Function',
|
||||
'Headers',
|
||||
'Infinity',
|
||||
'Int16Array',
|
||||
'Int32Array',
|
||||
'Int8Array',
|
||||
'Intl',
|
||||
'JSON',
|
||||
'Map',
|
||||
'Math',
|
||||
'NaN',
|
||||
'Number',
|
||||
'Object',
|
||||
'Promise',
|
||||
'Proxy',
|
||||
'RangeError',
|
||||
'ReferenceError',
|
||||
'Reflect',
|
||||
'RegExp',
|
||||
'Request',
|
||||
'Response',
|
||||
'Set',
|
||||
'SharedArrayBuffer',
|
||||
'String',
|
||||
'Symbol',
|
||||
'SyntaxError',
|
||||
'TypeError',
|
||||
'URIError',
|
||||
'Uint16Array',
|
||||
'Uint32Array',
|
||||
'Uint8Array',
|
||||
'Uint8ClampedArray',
|
||||
'VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL',
|
||||
'WeakMap',
|
||||
'WeakRef',
|
||||
'WeakSet',
|
||||
'WebAssembly',
|
||||
'__defineGetter__',
|
||||
'__defineSetter__',
|
||||
'__lookupGetter__',
|
||||
'__lookupSetter__',
|
||||
'__proto__',
|
||||
'clearImmediate',
|
||||
'clearInterval',
|
||||
'clearTimeout',
|
||||
'console',
|
||||
'constructor',
|
||||
'decodeURI',
|
||||
'decodeURIComponent',
|
||||
'dss',
|
||||
'encodeURI',
|
||||
'encodeURIComponent',
|
||||
'escape',
|
||||
'eval',
|
||||
'fetch',
|
||||
'global',
|
||||
'globalThis',
|
||||
'hasOwnProperty',
|
||||
'isFinite',
|
||||
'isNaN',
|
||||
'isPrototypeOf',
|
||||
'parseFloat',
|
||||
'parseInt',
|
||||
'process',
|
||||
'propertyIsEnumerable',
|
||||
'setImmediate',
|
||||
'setInterval',
|
||||
'setTimeout',
|
||||
'toLocaleString',
|
||||
'toString',
|
||||
'undefined',
|
||||
'unescape',
|
||||
'valueOf'
|
||||
];
|
||||
|
||||
public async setBreakpoint({ botId, line }) {
|
||||
GBLog.info(`BASIC: Enabled breakpoint for ${botId} on ${line}.`);
|
||||
|
|
|
@ -994,7 +994,7 @@ export class DialogKeywords {
|
|||
}
|
||||
} else if (kind === 'file') {
|
||||
GBLog.info(`BASIC (${min.botId}): Upload done for ${answer.filename}.`);
|
||||
const handle = WebAutomationServices.cyrb53(min.botId + answer.filename);
|
||||
const handle = WebAutomationServices.cyrb53({pid, str: min.botId + answer.filename});
|
||||
GBServer.globals.files[handle] = answer;
|
||||
result = handle;
|
||||
} else if (kind === 'boolean') {
|
||||
|
@ -1115,7 +1115,7 @@ export class DialogKeywords {
|
|||
} else if (kind === 'qr-scanner') {
|
||||
//https://github.com/GeneralBots/BotServer/issues/171
|
||||
GBLog.info(`BASIC (${min.botId}): Upload done for ${answer.filename}.`);
|
||||
const handle = WebAutomationServices.cyrb53(min.botId + answer.filename);
|
||||
const handle = WebAutomationServices.cyrb53({pid, str: min.botId + answer.filename});
|
||||
GBServer.globals.files[handle] = answer;
|
||||
QrScanner.scanImage(GBServer.globals.files[handle])
|
||||
.then(result => console.log(result))
|
||||
|
|
|
@ -81,6 +81,10 @@ import { GBUtil } from '../../../src/util.js';
|
|||
* BASIC system class for extra manipulation of bot behaviour.
|
||||
*/
|
||||
export class SystemKeywords {
|
||||
|
||||
/**
|
||||
* @tags System
|
||||
*/
|
||||
public async callVM({ pid, text }) {
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
const step = null;
|
||||
|
@ -2104,7 +2108,7 @@ export class SystemKeywords {
|
|||
|
||||
}
|
||||
|
||||
private cachedMerge = {};
|
||||
private cachedMerge:any = {};
|
||||
|
||||
/**
|
||||
* Merges a multi-value with a tabular file using BY field as key.
|
||||
|
|
|
@ -37,11 +37,10 @@ import Fs from 'fs';
|
|||
import Path from 'path';
|
||||
import url from 'url';
|
||||
|
||||
import { GBLog, GBMinInstance } from 'botlib';
|
||||
import { GBLog } from 'botlib';
|
||||
import { GBServer } from '../../../src/app.js';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js';
|
||||
import { GBSSR } from '../../core.gbapp/services/GBSSR.js';
|
||||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||
import { DialogKeywords } from './DialogKeywords.js';
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js';
|
||||
import { Mutex } from 'async-mutex';
|
||||
|
@ -55,10 +54,8 @@ export class WebAutomationServices {
|
|||
static isSelector(name: any) {
|
||||
return name.startsWith('.') || name.startsWith('#') || name.startsWith('[');
|
||||
}
|
||||
private debugWeb: boolean;
|
||||
private lastDebugWeb: Date;
|
||||
|
||||
public static cyrb53 = (str, seed = 0) => {
|
||||
|
||||
public static cyrb53 ({pid, str, seed = 0}) {
|
||||
let h1 = 0xdeadbeef ^ seed,
|
||||
h2 = 0x41c6ce57 ^ seed;
|
||||
for (let i = 0, ch; i < str.length; i++) {
|
||||
|
@ -152,7 +149,7 @@ export class WebAutomationServices {
|
|||
if ((!session && sessionKind === 'AS') || !sessionName) {
|
||||
// A new web session is being created.
|
||||
|
||||
handle = WebAutomationServices.cyrb53(min.botId + url);
|
||||
handle = WebAutomationServices.cyrb53({pid, str:min.botId + url});
|
||||
|
||||
session = {};
|
||||
session.sessionName = sessionName;
|
||||
|
@ -269,18 +266,21 @@ export class WebAutomationServices {
|
|||
|
||||
private async debugStepWeb(pid, page) {
|
||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||
|
||||
let debugWeb, lastDebugWeb; // TODO: Add this to pid bag.
|
||||
|
||||
let refresh = true;
|
||||
if (this.lastDebugWeb) {
|
||||
refresh = new Date().getTime() - this.lastDebugWeb.getTime() > 5000;
|
||||
if (lastDebugWeb) {
|
||||
refresh = new Date().getTime() - lastDebugWeb.getTime() > 5000;
|
||||
}
|
||||
|
||||
if (this.debugWeb && refresh) {
|
||||
if (debugWeb && refresh) {
|
||||
const mobile = min.core.getParam(min.instance, 'Bot Admin Number', null);
|
||||
const filename = page;
|
||||
if (mobile) {
|
||||
await new DialogKeywords().sendFileTo({ pid: pid, mobile, filename, caption: 'General Bots Debugger' });
|
||||
}
|
||||
this.lastDebugWeb = new Date();
|
||||
lastDebugWeb = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,98 @@ const waitUntil = condition => {
|
|||
});
|
||||
};
|
||||
|
||||
const systemVariables = [
|
||||
'AggregateError',
|
||||
'Array',
|
||||
'ArrayBuffer',
|
||||
'Atomics',
|
||||
'BigInt',
|
||||
'BigInt64Array',
|
||||
'BigUint64Array',
|
||||
'Boolean',
|
||||
'DataView',
|
||||
'Date',
|
||||
'Error',
|
||||
'EvalError',
|
||||
'FinalizationRegistry',
|
||||
'Float32Array',
|
||||
'Float64Array',
|
||||
'Function',
|
||||
'Headers',
|
||||
'Infinity',
|
||||
'Int16Array',
|
||||
'Int32Array',
|
||||
'Int8Array',
|
||||
'Intl',
|
||||
'JSON',
|
||||
'Map',
|
||||
'Math',
|
||||
'NaN',
|
||||
'Number',
|
||||
'Object',
|
||||
'Promise',
|
||||
'Proxy',
|
||||
'RangeError',
|
||||
'ReferenceError',
|
||||
'Reflect',
|
||||
'RegExp',
|
||||
'Request',
|
||||
'Response',
|
||||
'Set',
|
||||
'SharedArrayBuffer',
|
||||
'String',
|
||||
'Symbol',
|
||||
'SyntaxError',
|
||||
'TypeError',
|
||||
'URIError',
|
||||
'Uint16Array',
|
||||
'Uint32Array',
|
||||
'Uint8Array',
|
||||
'Uint8ClampedArray',
|
||||
'VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL',
|
||||
'WeakMap',
|
||||
'WeakRef',
|
||||
'WeakSet',
|
||||
'WebAssembly',
|
||||
'__defineGetter__',
|
||||
'__defineSetter__',
|
||||
'__lookupGetter__',
|
||||
'__lookupSetter__',
|
||||
'__proto__',
|
||||
'clearImmediate',
|
||||
'clearInterval',
|
||||
'clearTimeout',
|
||||
'console',
|
||||
'constructor',
|
||||
'decodeURI',
|
||||
'decodeURIComponent',
|
||||
'dss',
|
||||
'encodeURI',
|
||||
'encodeURIComponent',
|
||||
'escape',
|
||||
'eval',
|
||||
'fetch',
|
||||
'global',
|
||||
'globalThis',
|
||||
'hasOwnProperty',
|
||||
'isFinite',
|
||||
'isNaN',
|
||||
'isPrototypeOf',
|
||||
'parseFloat',
|
||||
'parseInt',
|
||||
'process',
|
||||
'propertyIsEnumerable',
|
||||
'setImmediate',
|
||||
'setInterval',
|
||||
'setTimeout',
|
||||
'toLocaleString',
|
||||
'toString',
|
||||
'undefined',
|
||||
'unescape',
|
||||
'valueOf'
|
||||
];
|
||||
|
||||
|
||||
export const createVm2Pool = ({ min, max, ...limits }) => {
|
||||
limits = Object.assign(
|
||||
{
|
||||
|
@ -112,7 +204,7 @@ export const createVm2Pool = ({ min, max, ...limits }) => {
|
|||
let variablesText = '';
|
||||
if (variables && variables.result) {
|
||||
await CollectionUtil.asyncForEach(variables.result, async v => {
|
||||
if (!DebuggerService.systemVariables.filter(x => x === v.name)[0]) {
|
||||
if (!systemVariables.filter(x => x === v.name)[0]) {
|
||||
if (v.value.value) {
|
||||
variablesText = `${variablesText} \n ${v.name}: ${v.value.value}`;
|
||||
}
|
||||
|
|
|
@ -1230,7 +1230,7 @@ export class GBMinService {
|
|||
|
||||
const t = new SystemKeywords();
|
||||
GBLog.info(`BASIC (${min.botId}): Upload done for ${attachmentData.fileName}.`);
|
||||
const handle = WebAutomationServices.cyrb53(min.botId + attachmentData.fileName);
|
||||
const handle = WebAutomationServices.cyrb53({pid:0, str:min.botId + attachmentData.fileName});
|
||||
let data = Fs.readFileSync(attachmentData.localPath);
|
||||
|
||||
const gbfile = {
|
||||
|
|
14
src/api.ts
Normal file
14
src/api.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { ImageProcessingServices } from '../packages/basic.gblib/services/ImageProcessingServices.js';
|
||||
import { SystemKeywords } from '../packages/basic.gblib/services/SystemKeywords.js';
|
||||
import { WebAutomationServices } from '../packages/basic.gblib/services/WebAutomationServices.js';
|
||||
import { DialogKeywords } from '../packages/basic.gblib/services/DialogKeywords.js';
|
||||
import { DebuggerService } from '../packages/basic.gblib/services/DebuggerService.js';
|
||||
|
||||
export interface GBAPI
|
||||
{
|
||||
systemKeywords: SystemKeywords;
|
||||
dialogKeywords: DialogKeywords;
|
||||
imageProcessing: ImageProcessingServices;
|
||||
webAutomation: WebAutomationServices;
|
||||
debuggerService: DebuggerService;
|
||||
}
|
32
src/app.ts
32
src/app.ts
|
@ -40,7 +40,9 @@ import https from 'https';
|
|||
import http from 'http';
|
||||
import mkdirp from 'mkdirp';
|
||||
import Path from 'path';
|
||||
import * as Fs from 'fs';
|
||||
import swaggerUI from 'swagger-ui-dist';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService.js';
|
||||
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||
|
@ -84,6 +86,7 @@ export class GBServer {
|
|||
}
|
||||
|
||||
const server = express();
|
||||
this.initEndpointsDocs(server);
|
||||
|
||||
GBServer.globals.server = server;
|
||||
GBServer.globals.httpsServer = null;
|
||||
|
@ -120,7 +123,7 @@ export class GBServer {
|
|||
|
||||
process.env.PWD = process.cwd();
|
||||
const workDir = Path.join(process.env.PWD, 'work');
|
||||
if (!Fs.existsSync(workDir)) {
|
||||
if (!fs.existsSync(workDir)) {
|
||||
mkdirp.sync(workDir);
|
||||
}
|
||||
|
||||
|
@ -299,7 +302,7 @@ export class GBServer {
|
|||
if (process.env.CERTIFICATE_PFX) {
|
||||
const options1 = {
|
||||
passphrase: process.env.CERTIFICATE_PASSPHRASE,
|
||||
pfx: Fs.readFileSync(process.env.CERTIFICATE_PFX)
|
||||
pfx: fs.readFileSync(process.env.CERTIFICATE_PFX)
|
||||
};
|
||||
|
||||
const httpsServer = https.createServer(options1, server).listen(port, mainCallback);
|
||||
|
@ -313,7 +316,7 @@ export class GBServer {
|
|||
if (process.env[certPfxEnv] && process.env[certPassphraseEnv] && process.env[certDomainEnv]) {
|
||||
const options = {
|
||||
passphrase: process.env[certPassphraseEnv],
|
||||
pfx: Fs.readFileSync(process.env[certPfxEnv])
|
||||
pfx: fs.readFileSync(process.env[certPfxEnv])
|
||||
};
|
||||
httpsServer.addContext(process.env[certDomainEnv], options);
|
||||
} else {
|
||||
|
@ -325,4 +328,25 @@ export class GBServer {
|
|||
server.listen(port, mainCallback);
|
||||
}
|
||||
}
|
||||
|
||||
public static initEndpointsDocs(app: express.Application) {
|
||||
const ENDPOINT = '/docs';
|
||||
const SWAGGER_FILE_NAME = 'swagger.yaml';
|
||||
const swaggerUiAssetPath = swaggerUI.getAbsoluteFSPath();
|
||||
|
||||
// A workaround for swagger-ui-dist not being able to set custom swagger URL
|
||||
const indexContent = fs
|
||||
.readFileSync(path.join(swaggerUiAssetPath, 'swagger-initializer.js'))
|
||||
.toString()
|
||||
.replace('https://petstore.swagger.io/v2/swagger.json', `/${SWAGGER_FILE_NAME}`);
|
||||
app.get(`${ENDPOINT}/swagger-initializer.js`, (req, res) => res.send(indexContent));
|
||||
|
||||
// Serve the swagger-ui assets
|
||||
app.use(ENDPOINT, express.static(swaggerUiAssetPath));
|
||||
|
||||
// Serve the swagger file
|
||||
app.get(`/${SWAGGER_FILE_NAME}`, (req, res) => {
|
||||
res.sendFile(path.join(process.env.PWD,SWAGGER_FILE_NAME));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
54
swagger.json
54
swagger.json
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"version": "3.0.0",
|
||||
"title": "General Bots API",
|
||||
"description": "General Bots API definitions.",
|
||||
"contact": {
|
||||
"name": "Pragmatismo",
|
||||
"url": "https://gb.pragmatismo.com.br",
|
||||
"email": "info@pragmatismo.com.br"
|
||||
},
|
||||
"x-ms-api-annotation": {
|
||||
"status": "Production"
|
||||
}
|
||||
},
|
||||
"host": "f993e4828c0d50.lhr.life",
|
||||
"basePath": "/",
|
||||
"schemes": [
|
||||
"https"
|
||||
],
|
||||
"consumes": [],
|
||||
"produces": [],
|
||||
"paths": {
|
||||
"/api/v2/dev-perdomo/dialog/talk": {
|
||||
"post": {
|
||||
"consumes":[
|
||||
"text/plain; charset=utf-8"
|
||||
],
|
||||
"summary": "Talk to the user.",
|
||||
"description": "Talk to the user.",
|
||||
"x-ms-no-generic-test": true,
|
||||
"operationId": "talk",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"TalkRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pid": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2956
swagger.yaml
Normal file
2956
swagger.yaml
Normal file
File diff suppressed because it is too large
Load diff
42
tsconfig.api.json
Normal file
42
tsconfig.api.json
Normal file
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": false,
|
||||
"allowJs": true,
|
||||
"downlevelIteration": true,
|
||||
"baseUrl": "./",
|
||||
"declaration": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"mapRoot": "./dist/",
|
||||
"moduleResolution": "Node",
|
||||
"module": "ESNext",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"*": [
|
||||
"types/*"
|
||||
],
|
||||
"botlib/*": [
|
||||
"node_modules/botlib/*"
|
||||
],
|
||||
"pragmatismo-io-framework/*": [
|
||||
"node_modules/pragmatismo-io-framework/*"
|
||||
]
|
||||
},
|
||||
"sourceMap": true,
|
||||
"target": "ESNext",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/api.ts",
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
Loading…
Add table
Reference in a new issue