From d33fc7e53a8b0a3b37fafdca0f844dd9fd6799e5 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Mon, 17 Nov 2025 15:21:46 +0800 Subject: [PATCH] dasdasd --- src/tools/account-register/sites/windsurf.js | 120 +++++++++++++++++-- 1 file changed, 109 insertions(+), 11 deletions(-) diff --git a/src/tools/account-register/sites/windsurf.js b/src/tools/account-register/sites/windsurf.js index 17cc06b..05d77cb 100644 --- a/src/tools/account-register/sites/windsurf.js +++ b/src/tools/account-register/sites/windsurf.js @@ -30,6 +30,7 @@ class WindsurfRegister { this.page = null; this.currentStep = 0; this.accountData = null; + this.sessionData = null; // 会话数据(用于浏览器切换) // 初始化 CapSolver(自动解决 Cloudflare Turnstile) this.capsolverKey = process.env.CAPSOLVER_API_KEY || null; @@ -185,13 +186,16 @@ class WindsurfRegister { } /** - * 初始化浏览器(使用 puppeteer-real-browser 自动绕过 Cloudflare) + * 初始化浏览器 + * @param {Object} options - 选项 + * @param {boolean} options.skipExtension - 是否跳过扩展加载(用于支付步骤) */ - async initBrowser() { + async initBrowser(options = {}) { const puppeteer = require('puppeteer'); const path = require('path'); - logger.info(this.siteName, '启动浏览器(集成 CapSolver 扩展)...'); + const browserType = options.skipExtension ? '干净浏览器(无扩展)' : '浏览器(集成 CapSolver 扩展)'; + logger.info(this.siteName, `启动${browserType}...`); // 随机视口大小 const viewports = [ @@ -211,8 +215,8 @@ class WindsurfRegister { ] }; - // 如果配置了 CapSolver,加载扩展 - if (this.capsolverKey) { + // 如果配置了 CapSolver 且 不跳过扩展,加载扩展 + if (!options.skipExtension && this.capsolverKey) { const fs = require('fs'); const os = require('os'); @@ -270,6 +274,8 @@ class WindsurfRegister { logger.warn(this.siteName, `⚠️ CapSolver 扩展未找到: ${extensionPath}`); logger.warn(this.siteName, '请检查扩展目录是否存在'); } + } else if (options.skipExtension) { + logger.info(this.siteName, '✓ 跳过扩展加载(避免干扰支付流程)'); } this.browser = await puppeteer.launch(launchOptions); @@ -310,6 +316,91 @@ class WindsurfRegister { } } + /** + * 保存会话数据(用于浏览器切换) + */ + async saveSession() { + logger.info(this.siteName, ' → 保存会话数据...'); + + this.sessionData = { + cookies: await this.page.cookies(), + localStorage: await this.page.evaluate(() => JSON.stringify(localStorage)), + sessionStorage: await this.page.evaluate(() => JSON.stringify(sessionStorage)), + url: this.page.url() + }; + + logger.success(this.siteName, ` → ✓ 会话数据已保存 (${this.sessionData.cookies.length} cookies)`); + } + + /** + * 恢复会话数据(用于浏览器切换) + */ + async restoreSession() { + if (!this.sessionData) { + throw new Error('没有可恢复的会话数据'); + } + + logger.info(this.siteName, ' → 恢复会话数据...'); + + // 1. 先访问域名(必须在同一域名下才能设置 cookies) + const url = new URL(this.sessionData.url); + await this.page.goto(url.origin, { waitUntil: 'networkidle2', timeout: 30000 }); + + // 2. 设置 cookies + await this.page.setCookie(...this.sessionData.cookies); + logger.info(this.siteName, ` → ✓ 已恢复 ${this.sessionData.cookies.length} 个 cookies`); + + // 3. 访问原始 URL + await this.page.goto(this.sessionData.url, { waitUntil: 'networkidle2', timeout: 30000 }); + + // 4. 恢复 localStorage 和 sessionStorage + await this.page.evaluate((ls, ss) => { + // 恢复 localStorage + const localData = JSON.parse(ls); + for (let key in localData) { + localStorage.setItem(key, localData[key]); + } + + // 恢复 sessionStorage + const sessionData = JSON.parse(ss); + for (let key in sessionData) { + sessionStorage.setItem(key, sessionData[key]); + } + }, this.sessionData.localStorage, this.sessionData.sessionStorage); + + // 5. 刷新页面以应用所有存储 + await this.page.reload({ waitUntil: 'networkidle2', timeout: 30000 }); + + logger.success(this.siteName, ' → ✓ 会话数据已恢复,登录状态保持'); + } + + /** + * 切换到干净的浏览器(无扩展) + */ + async switchBrowser() { + logger.info(this.siteName, ''); + logger.info(this.siteName, '┌─────────────────────────────────────────────────────┐'); + logger.info(this.siteName, '│ 🔄 切换到干净浏览器(避免扩展干扰支付) │'); + logger.info(this.siteName, '└─────────────────────────────────────────────────────┘'); + + // 1. 保存会话 + await this.saveSession(); + + // 2. 关闭当前浏览器 + logger.info(this.siteName, ' → 关闭带扩展的浏览器...'); + await this.browser.close(); + + // 3. 启动干净浏览器 + logger.info(this.siteName, ' → 启动干净浏览器(无扩展)...'); + await this.initBrowser({ skipExtension: true }); + + // 4. 恢复会话 + await this.restoreSession(); + + logger.success(this.siteName, '✓ 浏览器切换完成'); + logger.info(this.siteName, ''); + } + /** * 步骤1: 填写基本信息 */ @@ -463,7 +554,7 @@ class WindsurfRegister { // 点击按钮 await Promise.all([ - this.page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 }).catch(() => {}), + this.page.waitForNavigation({ waitUntil: 'load', timeout: 10000 }).catch(() => {}), this.human.humanClick(this.page, 'button:not([disabled])') ]); @@ -474,8 +565,8 @@ class WindsurfRegister { await this.page.keyboard.press('Enter'); } - // 等待页面稳定 - await this.human.randomDelay(2000, 3000); + // 等待页面稳定(优化:减少等待时间) + await this.human.randomDelay(500, 1000); // ===== Cloudflare Turnstile 验证处理 ===== @@ -531,7 +622,8 @@ class WindsurfRegister { logger.info(this.siteName, ` → 等待验证中... 已用时 ${elapsed/1000}秒`); } - await new Promise(resolve => setTimeout(resolve, 2000)); + // 优化:减少轮询间隔,更快检测到完成状态 + await new Promise(resolve => setTimeout(resolve, 500)); elapsed = Date.now() - startTime; } @@ -544,7 +636,7 @@ class WindsurfRegister { // 点击 Continue 进入邮箱验证 logger.info(this.siteName, ' → 点击Continue进入邮箱验证...'); await Promise.all([ - this.page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 15000 }).catch(() => {}), + this.page.waitForNavigation({ waitUntil: 'load', timeout: 10000 }).catch(() => {}), this.human.humanClick(this.page, 'button:not([disabled])') ]); @@ -1521,14 +1613,20 @@ class WindsurfRegister { this.currentStep = 5; logger.success(this.siteName, `步骤 5 完成 (共尝试 ${retryCount + 1} 次)`); + + // 保存会话数据(为步骤6的浏览器切换做准备) + await this.saveSession(); } /** - * 步骤6: 填写支付信息 + * 步骤6: 填写支付信息(在干净浏览器中完成) */ async step6_fillPayment() { logger.info(this.siteName, `[步骤 6/${this.getTotalSteps()}] 填写支付信息`); + // 切换到干净的浏览器(无扩展,避免干扰 Stripe) + await this.switchBrowser(); + try { // 等待页面加载 await this.human.readPage(3, 5);