aboutsummaryrefslogtreecommitdiff
path: root/lib/browser.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/browser.js')
-rw-r--r--lib/browser.js111
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/browser.js b/lib/browser.js
new file mode 100644
index 0000000..d0f7861
--- /dev/null
+++ b/lib/browser.js
@@ -0,0 +1,111 @@
+const puppeteer = require("puppeteer-extra");
+const StealthPlugin = require('puppeteer-extra-plugin-stealth');
+const cookiesStorage = require("./cookies-storage");
+puppeteer.use(StealthPlugin())
+
+const {getLogger} = require('./logging')
+
+const logger = getLogger('browser')
+
+
+const chromeOptions = {
+ headless: true,
+ args: []
+};
+
+let browser = null
+
+class PageWrapper {
+ constructor() {
+ this.intrNeededCallback = null
+ this.intrCallback = null
+ this.intrPostCallback = null
+
+ this.page = null
+ this.cdpClient = null
+ }
+
+ async getPage(interceptionNeededCallback, interceptCallback, postInterceptCallback) {
+ this.intrCallback = interceptCallback
+ this.intrNeededCallback = interceptionNeededCallback
+ this.intrPostCallback = postInterceptCallback
+
+ if (this.page !== null && this.page.isClosed()) {
+ this.page.removeAllListeners && this.page.removeAllListeners()
+ this.page = null
+ }
+
+ if (this.page !== null)
+ return this.page
+
+ this.page = await browser.newPage()
+
+ let cookies = await cookiesStorage.get()
+ // logger.debug('loaded cookies:', cookies)
+ await this.page.setCookie(...cookies)
+
+ this.page.on('domcontentloaded', async () => {
+ try {
+ let cookies = await this.page.cookies();
+ if (cookies)
+ await cookiesStorage.save(cookies)
+ } catch (e) {
+ logger.error('page.cookies() failed:', e)
+ }
+ })
+
+ await this.page.removeAllListeners('request')
+ await this.page.setRequestInterception(true)
+ this.page.on('request', async request => {
+ let contData = this.intrPostCallback(request)
+ await request.continue(contData)
+ })
+
+ this.cdpClient = await this.page.target().createCDPSession();
+ await this.cdpClient.send('Network.enable')
+ await this.cdpClient.send('Network.setRequestInterception', {
+ patterns: [
+ {
+ urlPattern: '*',
+ resourceType: 'Document',
+ interceptionStage: 'HeadersReceived'
+ }
+ ],
+ })
+ await this.cdpClient.on('Network.requestIntercepted', async e => {
+ let obj = {interceptionId: e.interceptionId}
+ if (this.intrNeededCallback && this.intrNeededCallback(e) === true) {
+ let ret = await this.cdpClient.send('Network.getResponseBodyForInterception', {
+ interceptionId: e.interceptionId
+ })
+ this.intrCallback(ret, e.responseHeaders)
+ obj['errorReason'] = 'BlockedByClient'
+ }
+ await this.cdpClient.send('Network.continueInterceptedRequest', obj)
+ })
+ return this.page
+ }
+}
+
+let singlePageWrapper = new PageWrapper()
+
+module.exports = {
+ async launch(options) {
+ if (options.proxy)
+ chromeOptions.args.push(`--proxy-server=${options.proxy}`)
+
+ if (options.noSandbox)
+ chromeOptions.args.push(
+ '--no-sandbox',
+ '--disable-setuid-sandbox'
+ )
+
+ if (options.headful)
+ chromeOptions.headless = false
+
+ browser = await puppeteer.launch(chromeOptions)
+ },
+
+ singlePageWrapper,
+ PageWrapper,
+} \ No newline at end of file