111 lines
3.3 KiB
JavaScript
111 lines
3.3 KiB
JavaScript
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,
|
|
} |