UNPKG

puppeteer-pro

Version:

A simple puppeteer wrapper to enable useful plugins with ease

278 lines 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Plugin = void 0; exports.connect = connect; exports.launch = launch; /* eslint-disable prefer-rest-params */ const events = require("events"); // Puppeteer Defaults const Puppeteer = require("puppeteer"); async function connect(options) { const browser = await Puppeteer.connect(options || {}); return createBrowser(browser); } async function launch(options) { if (!options) options = {}; process.env.PUPPETEER_DISABLE_HEADLESS_WARNING = 'true'; const browser = await Puppeteer.launch({ defaultViewport: undefined, ...options }); return createBrowser(browser); } async function createBrowser(puppeteerBrowser) { const browser = puppeteerBrowser; const _close = browser.close; browser.close = async () => { await _close.apply(browser); browser.browserEvents.emit('close'); }; const _createBrowserContext = browser.createBrowserContext; browser.createBrowserContext = async (options) => { const context = await _createBrowserContext.apply(browser, options); return createBrowserContext(context); }; const _newPage = browser.newPage; browser.newPage = async () => { const page = await _newPage.apply(browser); return newPage(page); }; addPluginSupport(browser); return browser; } async function createBrowserContext(puppeteerBrowserContext) { const browser = puppeteerBrowserContext; const _close = browser.close; browser.close = async () => { await _close.apply(browser); browser.browserEvents.emit('close'); }; const _newPage = browser.newPage; browser.newPage = async () => { const page = await _newPage.apply(browser); return newPage(page); }; addPluginSupport(browser); return browser; } function newPage(oldPage) { const page = oldPage; page.waitAndClick = async (selector, waitOptions, clickOptions) => { await page.waitForSelector(selector, waitOptions); await page.click(selector, clickOptions); }; page.waitAndType = async (selector, text, waitOptions, typeOptions) => { await page.waitForSelector(selector, waitOptions); await page.type(selector, text, typeOptions); }; return page; } function addPluginSupport(browser) { browser.plugins = []; browser.browserEvents = new events.EventEmitter(); browser.interceptions = 0; browser.addPlugin = async (plugin) => { browser.plugins.push(plugin); await plugin.init(browser); }; browser.clearPlugins = () => { browser.plugins.forEach(async (plugin) => { await plugin.stop(); }); browser.plugins = []; }; browser.anonymizeUserAgent = async () => { const plugin = new anonymize_user_agent_1.AnonymizeUserAgentPlugin(); await browser.addPlugin(plugin); return plugin; }; browser.avoidDetection = async (options) => { const plugin = new avoid_detection_1.AvoidDetectionPlugin(options); await browser.addPlugin(plugin); return plugin; }; browser.blockResources = async (...resources) => { const plugin = new block_resources_1.BlockResourcesPlugin(resources); await browser.addPlugin(plugin); return plugin; }; browser.disableDialogs = async (logMessages = false) => { const plugin = new disable_dialogs_1.DisableDialogsPlugin(logMessages); await browser.addPlugin(plugin); return plugin; }; browser.manageCookies = async (opts) => { const plugin = new manage_cookies_1.ManageCookiesPlugin(opts); await browser.addPlugin(plugin); return plugin; }; browser.manageLocalStorage = async (opts) => { const plugin = new manage_localstorage_1.ManageLocalStoragePlugin(opts); await browser.addPlugin(plugin); return plugin; }; browser.solveRecaptchas = async (accessToken) => { const plugin = new solve_recaptchas_1.SolveRecaptchasPlugin(accessToken); await browser.addPlugin(plugin); return plugin; }; } class Plugin { constructor() { this.browser = null; this.initialized = false; this.startCounter = 0; this.dependencies = []; this.requiresInterception = false; } get isInitialized() { return this.initialized; } get isStopped() { return this.startCounter === 0; } async addDependency(plugin) { this.dependencies.push(plugin); } async init(browser) { if (this.initialized) return; this.browser = browser; const offOnClose = []; browser.browserEvents.once('close', async () => { offOnClose.forEach(fn => fn()); this.browser = null; this.initialized = false; this.startCounter = 0; await this.onClose(); }); this.startCounter++; const thisOnTargetCreated = this.onTargetCreated.bind(this); browser.on('targetcreated', thisOnTargetCreated); offOnClose.push(() => browser.off('targetcreated', thisOnTargetCreated)); this.initialized = true; this.dependencies.forEach(x => x.init(browser)); return this.afterLaunch(browser); } async afterLaunch(_browser) { null; } async onClose() { null; } async onTargetCreated(target) { if (this.isStopped) return; if (target.type() !== 'page') return; const page = newPage(await target.page()); if (page.isClosed()) return; const offOnClose = []; page.once('close', async () => { offOnClose.forEach(fn => fn()); }); const requestHandlers = []; page.on('request', request => { const _respond = request.respond; let responded = 0; let respondArgs; const _abort = request.abort; let aborted = 0; let abortArgs; const _continue = request.continue; let continued = 0; let continueArgs; const handleRequest = async function () { const total = responded + aborted + continued; if (!request._interceptionHandled) { if (responded === 1) await _respond.apply(request, respondArgs); else if (responded === 0 && aborted >= 1 && total === requestHandlers.length) await _abort.apply(request, abortArgs); else if (continued === requestHandlers.length) await _continue.apply(request, continueArgs); } }; request.respond = async function () { responded++; respondArgs = respondArgs || arguments; await handleRequest(); }; request.abort = async function () { aborted++; abortArgs = abortArgs || arguments; await handleRequest(); }; request.continue = async function () { continued++; continueArgs = continueArgs || arguments; await handleRequest(); }; requestHandlers.forEach(handler => handler(request)); }); const _pageOn = page.on; page.on = function async(eventName, handler) { if (eventName === 'request') { requestHandlers.push(handler); return page; } else { return _pageOn.call(page, eventName, handler); } }; if (this.requiresInterception) { await page.setRequestInterception(true); const thisOnRequest = this.onRequest.bind(this); page.on('request', thisOnRequest); offOnClose.push(() => page.off('request', thisOnRequest)); } const thisOnDialog = this.onDialog.bind(this); page.on('dialog', thisOnDialog); offOnClose.push(() => page.off('dialog', thisOnDialog)); await this.onPageCreated(page); } async onPageCreated(_page) { null; } async onRequest(request) { const interceptionHandled = request._interceptionHandled; if (interceptionHandled) return; if (this.isStopped) return request.continue(); await this.processRequest(request); } async processRequest(_request) { null; } async onDialog(dialog) { if (this.isStopped) return; const _dismiss = dialog.dismiss; dialog.dismiss = async () => { if (dialog.handled) return; await _dismiss.apply(dialog); }; await this.processDialog(dialog); } async processDialog(_dialog) { null; } async beforeRestart() { null; } async restart() { await this.beforeRestart(); this.startCounter++; if (this.requiresInterception && this.browser) this.browser.interceptions++; this.dependencies.forEach(x => x.restart()); await this.afterRestart(); } async afterRestart() { null; } async beforeStop() { null; } async stop() { await this.beforeStop(); this.startCounter--; if (this.requiresInterception && this.browser) this.browser.interceptions--; if (this.browser && this.browser.interceptions === 0) { const pages = await this.browser.pages(); pages.filter(x => !x.isClosed()).forEach(async (page) => { await page.setRequestInterception(false); }); } this.dependencies.forEach(x => x.stop()); await this.afterStop(); } async afterStop() { null; } async getFirstPage() { if (!this.browser) return null; const pages = await this.browser.pages(); const openPages = pages.filter(x => !x.isClosed()); const activePages = pages.filter(x => x.url() !== 'about:blank'); return activePages[0] || openPages[0]; } } exports.Plugin = Plugin; const anonymize_user_agent_1 = require("./plugins/anonymize.user.agent"); const avoid_detection_1 = require("./plugins/avoid.detection"); const block_resources_1 = require("./plugins/block.resources"); const disable_dialogs_1 = require("./plugins/disable.dialogs"); const manage_cookies_1 = require("./plugins/manage.cookies"); const manage_localstorage_1 = require("./plugins/manage.localstorage"); const solve_recaptchas_1 = require("./plugins/solve.recaptchas"); //# sourceMappingURL=index.js.map