UNPKG

puppeteer-extra-plugin-timezone

Version:

A puppeteer-extra plugin to automatically emulate the appropriate timezones using IP reflection services.

124 lines 4.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TimezonePlugin = void 0; const puppeteer_extra_plugin_1 = require("puppeteer-extra-plugin"); const constants_1 = require("./constants"); const exceptions_1 = require("./exceptions"); const provider_1 = require("./provider"); const schemas_1 = require("./schemas"); /** * Puppeteer Extra Timezone Plugin * * @class * @classdesc Reflects public IP context and adjusts Chrome timezone to match expectation. */ class TimezonePlugin extends puppeteer_extra_plugin_1.PuppeteerExtraPlugin { /** * Constructor * Receives standard puppeteer-extra plugin config options. * * @param {TimezonePluginOptions} opts */ constructor(opts = {}) { super(opts); this._setFallbackTz(opts.fallbackTz); this.ctx = new Map(); } /** * Describe the identifier for plugin. * @return {string} */ get name() { return constants_1.PLUGIN_NAME; } /** * Accessor to previously resolved timezone strings. * @param {BrowserId} browserId * @return {string | undefined} */ getTz(browserId) { var _a; return (_a = this.ctx.get(browserId)) === null || _a === void 0 ? void 0 : _a.tz; } /** * Upon browser launch, attempt to resolve the timezone, if not already resolved. * * @param {Browser} browser * @return {Promise<void>} */ async onBrowser(browser) { var _a; const browserId = await this._getBrowserId(browser); try { // Create a new page to resolve ip context. const page = await browser.newPage(); // Save the ip context result to local property for future access. this.ctx.set(browserId, await provider_1.getTimezone(page)); // Clean up. await page.close(); this.debug(`Detected timezone (${constants_1.IP_REFLECTION_URL}): ${this.getTz(browserId)}`, this.ctx); browser.on("disconnected", () => this.ctx.delete(browserId)); } catch (err) { this.debug(`Error getting timezone for ip: ${err.message}`); this.debug((_a = err.stack) !== null && _a !== void 0 ? _a : err); } } /** * Each new page creation event, emulate the resolved timezone. * * @param {Page} page * @return {Promise<void>} */ async onPageCreated(page) { var _a; const browserId = await this._getBrowserId(page.browser()); // Get the resolved timezone or fallback timezone. const tz = this.getTz(browserId) || this._fallbackTz; // Do not emulate if we couldn't get any one of them. if (!tz) { throw new exceptions_1.TimezoneNotResolvedError(browserId); } // Attempt to emulate timezone based on previously resolved string. try { await page.emulateTimezone(tz); this.debug(`Emulating timezone ${tz} for ${page.url()}`); } catch (err) { this.debug(`Error emulating timezone for page (${page.url()}): ${err.message}`); this.debug((_a = err.stack) !== null && _a !== void 0 ? _a : err); } } /** * Returns the unique TargetId of a given browser. * * @see https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-getTargetInfo * @param {Browser} browser * @return {Promise<BrowserId>} * @protected */ async _getBrowserId(browser) { const browserInfo = schemas_1.TargetInfoSchema.parse(await (await browser.target().createCDPSession()).send("Target.getTargetInfo")); return browserInfo.targetInfo.targetId; } /** * Set the fallback value from options or defaults. * * @param {string | string[] | undefined} zones * @protected */ _setFallbackTz(zones) { let fallbacks = constants_1.DEFAULT_FALLBACK_TIMEZONES; if (zones) { fallbacks = typeof zones === "string" ? [zones] : zones; } this._fallbackTz = fallbacks[Math.floor(Math.random() * fallbacks.length)]; } } exports.TimezonePlugin = TimezonePlugin; /** * Export plugin factory as default export. * @return {TimezonePlugin} */ exports.default = () => new TimezonePlugin(); //# sourceMappingURL=plugin.js.map