From 0f1ee22467577c4237992d5d7bd3af8efd1ca300 Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Mon, 12 Sep 2022 08:52:51 -0300 Subject: [PATCH] fix(basic.gblib): SCREENSHOT keyword. --- package-lock.json | 181 +++++++++++++++++- package.json | 3 +- .../basic.gblib/services/ChartServices.ts | 8 +- .../basic.gblib/services/DialogKeywords.ts | 47 ++++- packages/basic.gblib/services/GBVMService.ts | 17 +- .../basic.gblib/services/SystemKeywords.ts | 5 +- packages/core.gbapp/services/GBSSR.ts | 19 +- 7 files changed, 246 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38ecec1d..5b33f12b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "botserver", - "version": "2.0.167", + "version": "2.0.173", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4185,6 +4185,14 @@ "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-0.9.46.tgz", "integrity": "sha512-LooLR6XHes9V+kNYRz1Qm8w3atw9QMn7XeZUmIpUelllF9BdryeUKd/u0Wh5ErcjpWfG39NrToU9MF7ngsTFVw==" }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "requires": { + "@types/ms": "*" + } + }, "@types/documentdb": { "version": "1.10.9", "resolved": "https://registry.npmjs.org/@types/documentdb/-/documentdb-1.10.9.tgz", @@ -4321,6 +4329,11 @@ "moment-timezone": "*" } }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, "@types/node": { "version": "14.0.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.22.tgz", @@ -5176,6 +5189,11 @@ "integrity": "sha1-oMoMvCmltz6Dbuvhy/bF4OTrgvk=", "dev": true }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" + }, "array-differ": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", @@ -8525,6 +8543,28 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" }, + "clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -12313,6 +12353,19 @@ "is-callable": "^1.1.3" } }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "requires": { + "for-in": "^1.0.1" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -14237,6 +14290,11 @@ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -16399,6 +16457,26 @@ "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", "dev": true }, + "merge-deep": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", + "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -16521,6 +16599,22 @@ } } }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==" + } + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -21338,6 +21432,65 @@ } } }, + "puppeteer-extra-plugin": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.2.tgz", + "integrity": "sha512-0uatQxzuVn8yegbrEwSk03wvwpMB5jNs7uTTnermylLZzoT+1rmAQaJXwlS3+vADUbw6ELNgNEHC7Skm0RqHbQ==", + "requires": { + "@types/debug": "^4.1.0", + "debug": "^4.1.1", + "merge-deep": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, + "puppeteer-extra-plugin-anonymize-ua": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-anonymize-ua/-/puppeteer-extra-plugin-anonymize-ua-2.4.4.tgz", + "integrity": "sha512-tdXCFrJLJl3Ykh4rz1s4mu9ih+/OI/1a1tIYmwxZHjBpb73bVoInFh6uKFBNZ0XHQWsa4TiBgBoMrOSog1+ooA==", + "requires": { + "debug": "^4.1.1", + "puppeteer-extra-plugin": "^3.2.2" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, + "puppeteer-extra-plugin-stealth": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-stealth/-/puppeteer-extra-plugin-stealth-2.4.5.tgz", + "integrity": "sha512-RUr9tvyvKOqH/yJ4tjcywbnkQbE99AhFD7uYKLO4YG0FIGNdaDdRrpiL2bgHo/bvIJDpfZwlO8YnhfmLnq6RNA==", + "requires": { + "debug": "^4.1.1", + "puppeteer-extra-plugin": "^3.1.2", + "puppeteer-extra-plugin-anonymize-ua": "^2.2.6" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -23054,6 +23207,32 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "shallow-clone": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", + "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^2.0.1", + "lazy-cache": "^0.2.3", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", + "requires": { + "is-buffer": "^1.0.2" + } + }, + "lazy-cache": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", + "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==" + } + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", diff --git a/package.json b/package.json index f6d75219..278278a1 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "prism-media": "1.3.1", "public-ip": "4.0.4", "puppeteer": "13.7.0", + "puppeteer-extra-plugin-stealth": "2.4.5", "qrcode": "^1.5.0", "qrcode-terminal": "0.12.0", "readline": "1.3.0", @@ -257,4 +258,4 @@ "post-merge": [] } } -} +} \ No newline at end of file diff --git a/packages/basic.gblib/services/ChartServices.ts b/packages/basic.gblib/services/ChartServices.ts index a3e4eedc..7bd304ee 100644 --- a/packages/basic.gblib/services/ChartServices.ts +++ b/packages/basic.gblib/services/ChartServices.ts @@ -32,11 +32,9 @@ 'use strict'; -const urlJoin = require('url-join'); -const DateDiff = require('date-diff'); const puppeteer = require('puppeteer'); -const Path = require('path'); -import bb from "billboard.js"; +const pluginStealth = require('puppeteer-extra-plugin-stealth'); + export class ChartServices { @@ -48,7 +46,7 @@ export class ChartServices { public static async screenshot(args, path) { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); - + // load billboard.js assets from CDN. await page.addStyleTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css" }); await page.addScriptTag({ url: "https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js" }); diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index c5e2d57e..b84fb8b0 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -44,13 +44,13 @@ import { GBMinService } from '../../core.gbapp/services/GBMinService'; import { HubSpotServices } from '../../hubspot.gblib/services/HubSpotServices'; import { WhatsappDirectLine } from '../../whatsapp.gblib/services/WhatsappDirectLine'; import { GBAdminService } from '../../admin.gbapp/services/GBAdminService'; -import { GBVMService } from './GBVMService'; const DateDiff = require('date-diff'); const puppeteer = require('puppeteer'); +const pluginStealth = require('puppeteer-extra-plugin-stealth'); + + const Path = require('path'); const sgMail = require('@sendgrid/mail'); -const PizZip = require("pizzip"); -const Docxtemplater = require("docxtemplater"); var mammoth = require("mammoth"); const qrcode = require('qrcode'); @@ -318,6 +318,26 @@ export class DialogKeywords { } } + /** + * Press ENTER in a web page, useful for logins. + * + * @example PRESS ENTER ON page + */ + public async pressKey(step, page, char, frame) { + GBLog.info(`BASIC: Web Automation PRESS ${char} ON element: ${frame}.`); + if (char.toLowerCase() === "enter") { + char = '\n'; + } + if (frame) { + await page.waitForSelector(frame) + let frameHandle = await page.$(frame); + const f = await frameHandle.contentFrame(); + await f.keyboard.press(char); + } + else { + await page.keyboard.press(char); + } + } public async linkByText(step, page, text, index) { GBLog.info(`BASIC: Web Automation CLICK LINK TEXT: ${text} ${index}.`); @@ -335,10 +355,23 @@ export class DialogKeywords { * * @example file = SCREENSHOT page */ - public async screenshot(step, page, idOrName, localName) { + public async screenshot(step, page, idOrName) { GBLog.info(`BASIC: Web Automation SCREENSHOT ${idOrName}.`); - const e = await this.getBySelector(page, idOrName); - await e.screenshot({ path: localName }); + + const gbaiName = `${this.min.botId}.gbai`; + const localName = Path.join('work', gbaiName, 'cache', `screen-${GBAdminService.getRndReadableIdentifier()}.jpg`); + + await page.screenshot({ path: localName }); + + const url = urlJoin( + GBServer.globals.publicAddress, + this.min.botId, + 'cache', + Path.basename(localName) + ); + GBLog.info(`BASIC: WebAutomation: Screenshot captured at ${url}.`); + + return url; } @@ -936,7 +969,7 @@ export class DialogKeywords { if (page) { const gbaiName = `${this.min.botId}.gbai`; const localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.jpg`); - await filename.screenshot({ path: localName }); + await filename.screenshot({ path: localName, fullPage: true }); const url = urlJoin( GBServer.globals.publicAddress, diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index 9dfb91f1..fa9df3c1 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -178,6 +178,7 @@ export class GBVMService extends GBService { username = step ? this.userName(step) : sys().getRandomId(); mobile = step ? this.userMobile(step) : sys().getRandomId(); from = mobile; + ENTER = String.fromCharCode(13); ubound = function(array){return array.length}; isarray = function(array){return Array.isArray(array) }; weekday = this.getWeekFromDate.bind(this); @@ -509,6 +510,14 @@ export class GBVMService extends GBService { return `sys().merge(${$1}, ${$2}, ${$3})\n`; }); + code = code.replace(/PRESS\s(.*)\sON\s(.*)/gi, ($0, $1, $2) => { + return `pressKey(step, ${$2}, ${$1})\n`; + }); + + code = code.replace(/SCREENSHOT\s(.*)/gi, ($0, $1, $2) => { + return `screenshot(step, ${$1})\n`; + }); + code = code.replace(/(\w+)\s*\=\s*(.*)\s*as image/gi, ($0, $1, $2) => { return `${$1} = sys().asImage(${$2})\n`; }); @@ -554,7 +563,7 @@ export class GBVMService extends GBService { // Removes comments. - basicCode = basicCode.replace(/(\n\s*REM.*\n)/gi, ''); + basicCode = basicCode.replace(/((^|\W)REM.*\n)/gi, ''); // Process INCLUDE keyword to include another // dialog inside the dialog. @@ -760,6 +769,12 @@ export class GBVMService extends GBService { code = code.replace(/("[^"]*"|'[^']*')|\blinkByText\b/gi, ($0, $1) => { return $1 === undefined ? 'this.linkByText' : $1; }); + code = code.replace(/("[^"]*"|'[^']*')|\bpressKey\b/gi, ($0, $1) => { + return $1 === undefined ? 'this.pressKey' : $1; + }); + code = code.replace(/("[^"]*"|'[^']*')|\bscreenshot\b/gi, ($0, $1) => { + return $1 === undefined ? 'this.screenshot' : $1; + }); code = code.replace(/("[^"]*"|'[^']*')|\bhover\b/gi, ($0, $1) => { return $1 === undefined ? 'this.hover' : $1; }); diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index 9854c900..b199e633 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -47,6 +47,9 @@ const Excel = require('exceljs'); const urlJoin = require('url-join'); const url = require('url'); const puppeteer = require('puppeteer') +const pluginStealth = require('puppeteer-extra-plugin-stealth'); + + const Path = require('path'); const ComputerVisionClient = require('@azure/cognitiveservices-computervision').ComputerVisionClient; const ApiKeyCredentials = require('@azure/ms-rest-js').ApiKeyCredentials; @@ -316,7 +319,7 @@ export class SystemKeywords { let localName; if (renderImage) { localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.png`); - await page.screenshot({ path: localName }); + await page.screenshot({ path: localName, fullPage: true }); url = urlJoin( GBServer.globals.publicAddress, this.min.botId, diff --git a/packages/core.gbapp/services/GBSSR.ts b/packages/core.gbapp/services/GBSSR.ts index 7bae28b5..3fa67e76 100644 --- a/packages/core.gbapp/services/GBSSR.ts +++ b/packages/core.gbapp/services/GBSSR.ts @@ -36,16 +36,8 @@ 'use strict'; -const Path = require('path'); -const urlJoin = require('url-join'); -const Fs = require('fs'); -const express = require('express'); -const child_process = require('child_process'); -const rimraf = require('rimraf'); -const request = require('request-promise-native'); -import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib'; -import { CollectionUtil } from 'pragmatismo-io-framework'; const puppeteer = require('puppeteer'); +const pluginStealth = require('puppeteer-extra-plugin-stealth'); import { NextFunction, Request, Response } from "express"; @@ -102,15 +94,6 @@ async function recursiveFindInFrames(inputFrame, selector) { return results.find(Boolean); } -async function findInFrames(page, selector) { - const result = await recursiveFindInFrames(page.mainFrame(), selector); - if (!result) { - throw new Error( - `The selector \`${selector}\` could not be found in any child frames.` - ); - } - return result; -}