new(all): #327 OPEN AS web automation.

This commit is contained in:
rodrigorodriguez 2023-02-15 22:12:24 -03:00
parent be5cf3f190
commit ea99337079
8 changed files with 70 additions and 35 deletions

View file

@ -1,7 +1,7 @@
dist: focal dist: focal
language: node_js language: node_js
node_js: node_js:
- 19.5.0 - 19.6.0
notifications: notifications:

View file

@ -14,7 +14,7 @@
"Dário Vieira <dario.junior3@gmail.com>" "Dário Vieira <dario.junior3@gmail.com>"
], ],
"engines": { "engines": {
"node": "=19.5.0" "node": "=19.6.0"
}, },
"license": "AGPL-3.0", "license": "AGPL-3.0",
"preferGlobal": true, "preferGlobal": true,
@ -76,6 +76,7 @@
"alasql": "2.1.6", "alasql": "2.1.6",
"any-shell-escape": "0.1.1", "any-shell-escape": "0.1.1",
"arraybuffer-to-buffer": "^0.0.7", "arraybuffer-to-buffer": "^0.0.7",
"async-mutex": "^0.4.0",
"async-promises": "0.2.3", "async-promises": "0.2.3",
"basic-auth": "2.0.1", "basic-auth": "2.0.1",
"billboard.js": "3.6.3", "billboard.js": "3.6.3",

View file

@ -140,12 +140,21 @@ export class KeywordsExpressions {
keywords[i++] = [ keywords[i++] = [
/^\s*open\s*(.*)/gim, /^\s*open\s*(.*)/gim,
($0, $1, $2) => { ($0, $1, $2) => {
let pos;
let sessionName;
if (pos = $1.match(/\s*AS\s*\#/)){
let part = $1.substr($1.lastIndexOf(pos[0]));
sessionName = `"${part.substr(part.indexOf("#") + 1)}"`;
$1 = $1.substr(0, $1.lastIndexOf(pos[0]));
}
if (!$1.startsWith('"') && !$1.startsWith("'")) { if (!$1.startsWith('"') && !$1.startsWith("'")) {
$1 = `"${$1}"`; $1 = `"${$1}"`;
} }
const params = this.getParams($1, ['url', 'username', 'password']); const params = this.getParams($1, ['url', 'username', 'password']);
return `page = await wa.getPage({pid: pid,${params}})`; return `page = await wa.getPage({pid: pid, sessionName: ${sessionName}, ${params}})`;
} }
]; ];

View file

@ -44,12 +44,15 @@ import urlJoin from 'url-join';
import Fs from 'fs'; import Fs from 'fs';
import Path from 'path'; import Path from 'path';
import url from 'url'; import url from 'url';
import { pid } from 'process'; import {Mutex, Semaphore, withTimeout} from 'async-mutex';
/** /**
* Web Automation services of conversation to be called by BASIC. * Web Automation services of conversation to be called by BASIC.
*/ */
export class WebAutomationServices { export class WebAutomationServices {
static semaphoreWithTimeout = withTimeout(new Semaphore(5), 60 * 1000, new Error('new fancy error'));
/** /**
* Reference to minimal bot instance. * Reference to minimal bot instance.
*/ */
@ -120,21 +123,33 @@ export class WebAutomationServices {
* *
* @example OPEN "https://wikipedia.org" * @example OPEN "https://wikipedia.org"
*/ */
public async getPage ({ pid, url, username, password }) {
GBLog.info(`BASIC: Web Automation GET PAGE ${url}.`); public async getPage({ pid, sessionName, url, username, password }) {
GBLog.info(`BASIC: Web Automation GET PAGE ${sessionName ? sessionName : ''} ${url}.`);
let page;
if (url.startsWith('#')) {
const [value, release] = await WebAutomationServices.semaphoreWithTimeout.acquire();
try {
page = GBServer.globals.webSessions[url.substr(1)];
} finally {
release();
}
} else {
if (!this.browser) { if (!this.browser) {
this.browser = await createBrowser(null); this.browser = await createBrowser(null);
} }
const page = (await this.browser.pages())[0]; page = (await this.browser.pages())[0];
if (sessionName) {
GBServer.globals.webSessions[sessionName] = page;
}
if (username || password) { if (username || password) {
await page.authenticate({ pid, username: username, password: password }); await page.authenticate({ pid, username: username, password: password });
} }
}
await page.goto(url); await page.goto(url);
const handle = WebAutomationServices.cyrb53(this.min.botId + url); const handle = WebAutomationServices.cyrb53(this.min.botId + url);
this.pageMap[handle] = page; this.pageMap[handle] = page;
return handle; return handle;
} }

View file

@ -37,7 +37,7 @@
'use strict'; 'use strict';
import { GBLog, IGBInstance } from "botlib"; import { GBLog, IGBInstance } from "botlib";
import { GuaribasLog } from "../models/GBModel"; import { GuaribasLog } from "../models/GBModel.js";
export class GBLogEx { export class GBLogEx {
public static async error(minOrInstanceId: any, message: string) { public static async error(minOrInstanceId: any, message: string) {
@ -76,6 +76,7 @@ export class GBLogEx {
* Finds and update user agent information to a next available person. * Finds and update user agent information to a next available person.
*/ */
public static async log(instance: IGBInstance, kind: string, message: string): Promise<GuaribasLog> { public static async log(instance: IGBInstance, kind: string, message: string): Promise<GuaribasLog> {
message = message?message.substring(0,1023):null;
return await GuaribasLog.create(<GuaribasLog>{ return await GuaribasLog.create(<GuaribasLog>{
instanceId: instance.instanceId, instanceId: instance.instanceId,
message: message, message: message,

View file

@ -36,11 +36,17 @@
'use strict'; 'use strict';
import puppeteer from 'puppeteer-extra';
import {createRequire} from "module";
const require = createRequire(import.meta.url);
const puppeteer = require('puppeteer-extra');
const hidden = require('puppeteer-extra-plugin-stealth')
// require executablePath from puppeteer
const {executablePath} = require('puppeteer')
import Fs from 'fs'; import Fs from 'fs';
// const StealthPlugin from 'puppeteer-extra-plugin-stealth')
// puppeteer.use(StealthPlugin());
import { NextFunction, Request, Response } from 'express'; import { NextFunction, Request, Response } from 'express';
import urljoin from 'url-join'; import urljoin from 'url-join';
@ -96,12 +102,13 @@ async function createBrowser (profilePath): Promise<any> {
Fs.writeFileSync(preferences, JSON.stringify(data)); Fs.writeFileSync(preferences, JSON.stringify(data));
} }
} }
puppeteer.use(hidden())
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
args: args, args: args,
ignoreHTTPSErrors: true, ignoreHTTPSErrors: true,
headless: false, headless: false,
defaultViewport: null, defaultViewport: null,
executablePath:executablePath(),
ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection'] ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection']
}); });
return browser; return browser;

View file

@ -42,6 +42,7 @@ import { GBMinService } from '../packages/core.gbapp/services/GBMinService.js';
*/ */
export class RootData { export class RootData {
public webSessions: {} // List of Web Automation sessions.
public processes: {}; // List of .gbdialog active executions. public processes: {}; // List of .gbdialog active executions.
public files: {}; // List of uploaded files handled. public files: {}; // List of uploaded files handled.
public publicAddress: string; // URI for BotServer. public publicAddress: string; // URI for BotServer.

View file

@ -84,6 +84,7 @@ export class GBServer {
const server = express(); const server = express();
GBServer.globals.server = server; GBServer.globals.server = server;
GBServer.globals.webSessions = {};
GBServer.globals.processes = {}; GBServer.globals.processes = {};
GBServer.globals.files = {}; GBServer.globals.files = {};
GBServer.globals.appPackages = []; GBServer.globals.appPackages = [];