-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
125 lines (113 loc) · 3.55 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
'use strict'
const { LOCALES } = require('./locales.js');
const { PuppeteerExtraPlugin } = require('puppeteer-extra-plugin');
/**
* Force to fetch pages with certain language in puppeteer.
*
* @param {Object} [opts={}] - Plugin options
* @param {String} [opts.language='en'] - Language to emulate
* @param {Boolean} [opts.ip=true] - Enable/Disable ip spoofing technique
* @param {Boolean} [opts.httpHeaders=true] - Enable/Disable HTTP-headers language related spoofing technique
* @param {Boolean} [opts.geolocation=true] - Enable/Disable browser geolocation spoofing techinque
* @param {Boolean} [opts.javascript=true] - Enable/Disable javascript spoofing technique
*
* @example
* const puppeteer = require('puppeteer-extra')
* puppeteer.use(require('puppeteer-extra-plugin-force-custom-language')())
* // or
* puppeteer.use(require('puppeteer-extra-plugin-force-custom-language')({language: 'es'}))
* const browser = await puppeteer.launch()
* // or
* puppeteer.use(require('puppeteer-extra-plugin-force-custom-language')({
* language: 'ru',
* ip: true,
* javascript: true,
* geoLocation: true,
* httpHeaders: true,
* requestInterceptionPriority: -1})
* )
* const browser = await puppeteer.launch()
*
* @author thewolfx41 <[email protected]>
* @version 1.0.0
*/
class ForceCustomLanguagePlugin extends PuppeteerExtraPlugin {
constructor(opts = {}) {
super(opts)
if (opts?.language && Object.keys(LOCALES).includes(opts.language)) {
this._locale = LOCALES[opts.language];
} else {
this._locale = LOCALES[this.defaults.language];
}
}
get defaults() {
return {
language: 'en',
ip: true,
httpHeaders: true,
geoLocation: true,
javascript: true,
requestInterceptionPriority: -1
}
}
get name() {
return 'force-custom-language';
}
get requirements() {
return new Set(['runLast'])
}
async beforeLaunch(options) {
options.devtools = true;
options.args.push(`--lang=${this._locale.languageCode}`);
}
async onPageCreated(page) {
if (this.opts.ip) {
await page.setExtraHTTPHeaders({
'X-Real-Ip': this._locale.ip,
'X-Forwarded-For': this._locale.ip,
});
}
if (this.opts.httpHeaders) {
await page.setRequestInterception(true);
page.on('request', (interceptedRequest) => {
if (interceptedRequest.isInterceptResolutionHandled()) return;
const headerOverride = interceptedRequest.headers();
headerOverride['Accept-Language'] = `${this._locale.locale},${this._locale.languageCode}`;
interceptedRequest.continue({
headers: headerOverride,
}, this.opts.requestInterceptionPriority);
});
}
if (this.opts.geoLocation) await page.setGeolocation({latitude: this._locale.latitude, longitude: this._locale.longitude});
if (this.opts.javascript) {
await page.evaluateOnNewDocument((langs) => {
Object.defineProperty(navigator, 'language', {
get: function () {
return langs[0];
},
});
Object.defineProperty(navigator, 'languages', {
get: function () {
return langs[1];
},
});
}, [this._locale.locale, [this._locale.locale, this._locale.languageCode]]);
}
}
async onTargetChanged(target) {
if (this.opts.geoLocation) {
const _url = target.url();
const _browser = target.browser();
const ctx = _browser.defaultBrowserContext();
try {
//await ctx.clearPermissionOverrides();
await ctx.overridePermissions(_url, ['geolocation']);
} catch(e) {
this.debug(`Cannot overridePermission on this site: ${_url}`);
}
}
}
}
module.exports = function (pluginConfig) {
return new ForceCustomLanguagePlugin(pluginConfig)
}