diff --git a/package.json b/package.json index a4d41d0..76529c3 100644 --- a/package.json +++ b/package.json @@ -1,32 +1,37 @@ -{ - "name": "youchat-proxy", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "cookie": "^0.6.0", - "docx": "^8.5.0", - "express": "^4.19.2", - "form-data": "^4.0.0", - "puppeteer-real-browser": "1.2.22", - "puppeteer-core": "^23.10.4", - "uuid": "^9.0.1", - "localtunnel": "^2.0.2", - "socks-proxy-agent": "^8.0.4", - "https-proxy-agent": "^7.0.5", - "ngrok": "^5.0.0-beta.2", - "node-fetch": "^3.3.2", - "socket.io-client": "^4.8.0", - "crypto-js": "^4.2.0", - "async-mutex": "^0.5.0", - "geoip-lite": "^1.4.10", - "cookie-parser": "^1.4.7", - "winston": "^3.17.0", - "dayjs": "^1.11.13" - } -} +{ + "name": "youchat-proxy", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "async-mutex": "^0.5.0", + "cookie": "^0.6.0", + "cookie-parser": "^1.4.7", + "crypto-js": "^4.2.0", + "dayjs": "^1.11.13", + "docx": "^8.5.0", + "express": "^4.19.2", + "form-data": "^4.0.0", + "geoip-lite": "^1.4.10", + "https-proxy-agent": "^7.0.5", + "localtunnel": "^2.0.2", + "ngrok": "^5.0.0-beta.2", + "node-fetch": "^3.3.2", + "puppeteer-core": "^24.4.0", + "puppeteer-real-browser": "^1.4.2", + "socket.io-client": "^4.8.0", + "socks-proxy-agent": "^8.0.4", + "unzipper": "^0.12.3", + "uuid": "^9.0.1", + "winston": "^3.17.0", + "ws": "^8.18.1" + }, + "devDependencies": { + "playwright": "^1.51.0" + } +} diff --git a/sessionManager.mjs b/sessionManager.mjs index 6efc0d5..f735e3d 100644 --- a/sessionManager.mjs +++ b/sessionManager.mjs @@ -2,8 +2,11 @@ import fs from 'fs'; import path from 'path'; import {Mutex} from 'async-mutex'; import {detectBrowser} from './utils/browserDetector.mjs'; -import {createDirectoryIfNotExists} from './utils.mjs'; +import {createDirectoryIfNotExists} from './utils/cookieUtils.mjs'; import {fileURLToPath} from 'url'; +import {optimizeBrowserDisplay} from './utils/browserDisplayFixer.mjs'; +import {launchEdgeBrowser} from './utils/edgeLauncher.mjs'; +import {setupBrowserFingerprint} from './utils/browserFingerprint.mjs'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -172,46 +175,129 @@ class SessionManager { async launchSingleBrowser(browserId, userDataDir, browserPath) { let browser, page; - if (isHeadless === false) { - // 使用 puppeteer-real-browser - const response = await connect({ - headless: 'auto', - turnstile: true, - customConfig: { - userDataDir: userDataDir, + const isEdge = browserPath.toLowerCase().includes('msedge') || + process.env.BROWSER_TYPE === 'edge'; + if (isEdge) { + try { + const debugPort = 9222 + parseInt(browserId.replace('browser_', ''), 10); + const result = await launchEdgeBrowser(userDataDir, browserPath, debugPort); + browser = result.browser; + page = result.page; + + console.log(`Edge浏览器启动成功 (browserId=${browserId})`); + } catch (error) { + console.error(`原生启动Edge失败:`, error); + console.log(`回退标准方式启动浏览器...`); + } + } + + if (!browser) { + if (isHeadless === false) { + // 使用 puppeteer-real-browser + const response = await connect({ + headless: 'auto', + turnstile: true, + customConfig: { + userDataDir: userDataDir, + executablePath: browserPath, + args: [ + '--no-sandbox', + '--disable-setuid-sandbox', + '--remote-debugging-address=::', + '--window-size=1280,850', + '--force-device-scale-factor=1', + ], + }, + }); + browser = response.browser; + page = response.page; + } else { + // 使用 puppeteer-core + browser = await puppeteerModule.launch({ + headless: this.isHeadless, executablePath: browserPath, + userDataDir: userDataDir, args: [ '--no-sandbox', '--disable-setuid-sandbox', - '--remote-debugging-address=::', + '--disable-gpu', + '--disable-dev-shm-usage', + '--remote-debugging-port=0', + '--window-size=1280,850', + '--force-device-scale-factor=1', ], - }, - }); - browser = response.browser; - page = response.page; - } else { - // 使用 puppeteer-core - browser = await puppeteerModule.launch({ - headless: this.isHeadless, - executablePath: browserPath, - userDataDir: userDataDir, - args: [ - '--no-sandbox', - '--disable-setuid-sandbox', - '--disable-gpu', - '--disable-dev-shm-usage', - '--remote-debugging-port=0', - ], - }); - page = await browser.newPage(); + }); + page = await browser.newPage(); + } } - return { - id: browserId, - browser: browser, - page: page, - locked: false, - }; + const originalUserAgent = await page.evaluate(() => navigator.userAgent); + // console.log(`浏览器 ${browserId} 原始用户代理: ${originalUserAgent}`); + + const browserType = isEdge ? 'edge' : 'chrome'; + const fingerprint = await setupBrowserFingerprint(page, browserType); + + try { + const newUserAgent = await page.evaluate(() => navigator.userAgent); + const newPlatform = await page.evaluate(() => navigator.platform); + const newCores = await page.evaluate(() => navigator.hardwareConcurrency); + + // console.log(`浏览器 ${browserId} 应用指纹后:`); + // console.log(`- 用户代理: ${newUserAgent}`); + // console.log(`- 平台: ${newPlatform}`); + // console.log(`- CPU核心: ${newCores}`); + // console.log(`- 内存: ${fingerprint.ram}GB`); + // console.log(`- 设备名称: ${fingerprint.deviceName}`); + + const isActuallyEdge = newUserAgent.includes('Edg'); + + // 应用显示优化 + try { + await optimizeBrowserDisplay(page, { + width: 1280, + height: 850, + deviceScaleFactor: 1, + cssScale: 1, + fixHighDpi: true, + isHeadless: this.isHeadless + }); + } catch (error) { + console.warn(`显示优化失败:`, error); + } + + return { + id: browserId, + browser: browser, + page: page, + locked: false, + isEdgeBrowser: isActuallyEdge, + fingerprint: fingerprint // 存储指纹信息 + }; + } catch (error) { + console.error(`验证指纹时出错:`, error); + + try { + await optimizeBrowserDisplay(page, { + width: 1280, + height: 850, + deviceScaleFactor: 1, + cssScale: 1, + fixHighDpi: true, + isHeadless: this.isHeadless + }); + } catch (displayError) { + console.warn(`显示优化失败:`, displayError); + } + + const isActuallyEdge = originalUserAgent.includes('Edg'); + return { + id: browserId, + browser: browser, + page: page, + locked: false, + isEdgeBrowser: isActuallyEdge + }; + } } async getAvailableBrowser() { @@ -420,4 +506,4 @@ function shuffleArray(array) { } } -export default SessionManager; +export default SessionManager; \ No newline at end of file