-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* proper handling of exceptions. * action-router model * Now we throw errors and action is more error-prone. * compose action * Fix everything... * Working service! * Docs * Fixes after review * Fixes after review
- Loading branch information
1 parent
b37e0ae
commit 8139dee
Showing
30 changed files
with
406 additions
and
290 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
const exceptions = require('../helpers/exceptions'); | ||
const utils = require('../helpers/utils'); // For usage inside user's action(page, request) function | ||
|
||
/** | ||
* Content-Type: application/javascript | ||
* body = js function as pattern: | ||
* async function action(page, request) { | ||
* ... | ||
* some actions with page in puppeteer syntax | ||
* ... | ||
* return { | ||
* context_id: page.browserContext().id, | ||
* page_id: page.target()._targetId, | ||
* html: await page.content(), | ||
* cookies: await page.cookies() | ||
* }; | ||
* }; | ||
*/ | ||
exports.action = async function action(page, request) { | ||
eval(request.body.toString()); | ||
|
||
// check action function existence | ||
if (!(typeof action === "function" && action.length >= 1)) { | ||
throw new exceptions.IncorrectArgumentError("Invalid action function.\n" + | ||
"Valid action function: \"async function action(page, request) " + | ||
"{ ... some actions with request and page in puppeteer " + | ||
"syntax};\""); | ||
} | ||
|
||
return { | ||
data: await action(page, request) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const utils = require('../helpers/utils'); | ||
|
||
const DEFAULT_TIMEOUT = 1000; // 1 second | ||
|
||
/* | ||
* body = { | ||
* "selector": "", // <string> A selector to search for element to click. If there are multiple elements satisfying the selector, the first will be clicked. | ||
* "clickOptions": { | ||
* "button", // <"left"|"right"|"middle"> Defaults to left. | ||
* "clickCount", // <number> defaults to 1. | ||
* "delay" // <number> Time to wait between mousedown and mouseup in milliseconds. Defaults to 0. | ||
* }, | ||
* "waitOptions": {...}, // same as in goto action, defaults to 1s timeout | ||
* "navigationOptions": {...} // same as in goto action | ||
* } | ||
*/ | ||
exports.click = async function click(page, request) { | ||
await page.hover(request.body.selector); | ||
if (request.body.navigationOptions) { | ||
await Promise.all([ | ||
page.waitForNavigation(request.body.navigationOptions), | ||
page.click(request.body.selector, request.body.clickOptions), | ||
]); | ||
} else { | ||
await page.click(request.body.selector, request.body.clickOptions); | ||
} | ||
const waitOptions = request.body.waitOptions || { timeout: DEFAULT_TIMEOUT }; | ||
return await utils.getContents(page, waitOptions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
endpoint2action = { | ||
action: require("./action").action, | ||
click: require("./click").click, | ||
fill_form: require("./fill_form").fillForm, | ||
back: require("./goback").goBack, | ||
forward: require("./goforward").goForward, | ||
goto: require("./goto").goto, | ||
har: require("./har").har, | ||
mhtml: require("./mhtml").captureSnapshot, | ||
recaptcha_solver: require("./recaptcha_solver").recaptchaSolver, | ||
screenshot: require("./screenshot").screenshot, | ||
scroll: require("./scroll").scroll, | ||
} | ||
|
||
async function compose(page, request) { | ||
const originalClosePage = request.query.closePage; | ||
const originalBody = structuredClone(request.body); | ||
|
||
request.query.closePage = false; | ||
delete request.body["actions"]; | ||
|
||
let response; | ||
try { | ||
for (const action of originalBody["actions"]) { | ||
request.body = action["body"]; | ||
response = await endpoint2action[action["endpoint"]](page, request); | ||
} | ||
} finally { | ||
request.query.closePage = originalClosePage; | ||
request.body = originalBody; | ||
} | ||
|
||
return response; | ||
} | ||
exports.compose = compose; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const utils = require('../helpers/utils'); | ||
|
||
/* | ||
* body = { | ||
* "inputMapping": { A dictionary where each key is a CSS selector, and each value is another dictionary containing details about the input for that element: | ||
* "selector": <string> The CSS selector for the input element (used as the key). | ||
* "value": <string> The text to be inputted into the element. | ||
* "delay": <number> A delay (in milliseconds) between each keystroke when inputting the text. Defaults to 0 if not provided. | ||
* }, | ||
* "submitButton": <string> The CSS selector for the form's submit button. If provided, the button will be clicked after filling in the form. | ||
* } | ||
*/ | ||
exports.fillForm = async function fillForm(page, request) { | ||
const inputMapping = request.body.inputMapping; | ||
const submitButton = request.body.submitButton; | ||
|
||
for (const [selector, params] of Object.entries(inputMapping)) { | ||
const value = params.value; | ||
const delay = params.delay || 0; | ||
await page.type(selector, value, { delay }); | ||
} | ||
|
||
if (submitButton) { | ||
await page.click(submitButton); | ||
} | ||
|
||
return await utils.getContents(page); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const utils = require('../helpers/utils'); | ||
|
||
exports.goBack = async function goBack(page, request) { | ||
await page.goBack(request.body.navigationOptions); | ||
return await utils.getContents(page, request.body.waitOptions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const utils = require('../helpers/utils'); | ||
|
||
exports.goForward = async function goForward(page, request) { | ||
await page.goForward(request.body.navigationOptions); | ||
return await utils.getContents(page, request.body.waitOptions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
const utils = require('../helpers/utils'); | ||
|
||
/* | ||
* body = { | ||
* "url": <string> URL to navigate page to. The url should include scheme, e.g. https://. | ||
* "navigationOptions": { Navigation parameters which might have the following properties: | ||
* "timeout": <number> Maximum navigation time in milliseconds, defaults to 30 seconds, pass 0 to disable timeout. The default value can be changed by using the page.setDefaultNavigationTimeout(timeout) or page.setDefaultTimeout(timeout) methods. | ||
* "waitUntil": <string|Array<string>> When to consider navigation succeeded, defaults to load. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events can be either: | ||
* load - consider navigation to be finished when the load event is fired. | ||
* domcontentloaded - consider navigation to be finished when the DOMContentLoaded event is fired. | ||
* networkidle0 - consider navigation to be finished when there are no more than 0 network connections for at least 500 ms. | ||
* networkidle2 - consider navigation to be finished when there are no more than 2 network connections for at least 500 ms. | ||
* "referer" <string> Referer header value. If provided it will take preference over the referer header value set by page.setExtraHTTPHeaders(). | ||
* }, | ||
* "waitOptions": { | ||
* "timeout": <number> Wait for given timeout in milliseconds | ||
* "selector": <string> Wait for element by selector (see https://pptr.dev/api/puppeteer.page.waitforselector) | ||
* "xpath": <string> Wait for element by xpath (see https://pptr.dev/api/puppeteer.page.waitforxpath) | ||
* "options": <object> Options to wait for elements (see https://pptr.dev/api/puppeteer.waitforselectoroptions) | ||
* }, | ||
* "harRecording": true, | ||
* } | ||
*/ | ||
exports.goto = async function goto(page, request) { | ||
await page.goto(request.body.url, request.body.navigationOptions); | ||
return await utils.getContents(page, request.body.waitOptions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const exceptions = require("../helpers/exceptions"); | ||
|
||
exports.har = async function har(page, request) { | ||
if (!(page.harWriter)){ | ||
throw new exceptions.NoHarWriterError(); | ||
} | ||
|
||
return { | ||
har: JSON.stringify(await page.harWriter.stop()) // TODO: do we really need JSON.stringify? | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* Captures mhtml snapshot of a page | ||
*/ | ||
exports.captureSnapshot = async function captureSnapshot(page, request) { | ||
const cdpSession = await page.target().createCDPSession(); | ||
const { data } = await cdpSession.send('Page.captureSnapshot', { format: 'mhtml' }); | ||
await cdpSession.detach() | ||
return { | ||
mhtml: data, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
const utils = require('../helpers/utils') | ||
|
||
const DEFAULT_TIMEOUT = 1000; // 1 second | ||
|
||
/* | ||
* This module introduces new ability to puppeteer-service. | ||
* It is capable of solving recaptchas on a given web-page. | ||
* If there is no recaptcha on the page nothing bad will happen. | ||
* If there is recaptcha it solves it and then inserts the special code | ||
* into the page automatically. | ||
* | ||
* Returns useful information about recaptcha_solving. | ||
* For more information about return value visit | ||
* https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-recaptcha#result-object | ||
*/ | ||
exports.recaptchaSolver = async function recaptchaSolver(page, request) { | ||
let recaptcha_data; | ||
|
||
if (request.body.solve_recaptcha) { | ||
recaptcha_data = await page.solveRecaptchas(); | ||
} else { | ||
recaptcha_data = await page.findRecaptchas(); | ||
} | ||
|
||
const waitOptions = request.body.waitOptions || { timeout: DEFAULT_TIMEOUT }; | ||
const contents = await utils.getContents(page, waitOptions); | ||
|
||
if (request.query.closePage || | ||
(request.body.close_on_empty && recaptcha_data['captchas'].length === 0)) { | ||
await page.close(); | ||
} | ||
|
||
return { | ||
...contents, | ||
recaptcha_data: recaptcha_data, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* Method that returns screenshots of pages | ||
* more description of options you can see on GitHub: | ||
* https://github.com/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md#pagescreenshotoptions | ||
*/ | ||
exports.screenshot = async function screenshot(page, request) { | ||
delete request.body.options.path; // no path for saving images | ||
request.body.options.encoding = "base64"; // return in base64 | ||
let screenshot = await page.screenshot(request.body.options); | ||
return { | ||
screenshot: screenshot | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const utils = require('../helpers/utils'); | ||
|
||
const DEFAULT_TIMEOUT = 1000; // 1 second | ||
|
||
/* | ||
* Method that scrolls page to a certain selector. | ||
* Example body: | ||
* body = { | ||
* "selector": "", // <string> A selector to search for element to scroll | ||
* "waitOptions": {...}, // same as in goto action, defaults to 1s timeout | ||
* } | ||
*/ | ||
exports.scroll = async function scroll(page, request) { | ||
if (request.body.selector) { | ||
await page.hover(request.body.selector); | ||
} else { | ||
await page.evaluate(() => { | ||
// scroll down until the bottom of the page to trigger scroll event even at the bottom of a page | ||
window.scrollBy(0, document.body.scrollHeight) | ||
}); | ||
} | ||
const waitOptions = request.body.waitOptions || { timeout: DEFAULT_TIMEOUT}; | ||
return utils.getContents(page, waitOptions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.