auto-account-machine/src/tools/account-register/sites/windsurf.js
dengqichen bf55bcee27 aaaaa
2025-11-16 19:46:13 +08:00

379 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Windsurf Register - Windsurf网站注册
* https://windsurf.com/account/register
*
* 注册流程:
* Step 1: 填写基本信息First Name, Last Name, Email
* Step 2: 设置密码
* Step 3: 邮箱验证
* Step 4: 完善个人信息
* ... 根据实际情况继续添加步骤
*/
const AccountDataGenerator = require('../generator');
const HumanBehavior = require('../utils/human-behavior');
const logger = require('../../../shared/logger');
class WindsurfRegister {
constructor() {
this.siteName = 'Windsurf';
this.siteUrl = 'https://windsurf.com/account/register';
this.dataGen = new AccountDataGenerator();
this.human = new HumanBehavior();
this.browser = null;
this.page = null;
this.currentStep = 0;
this.accountData = null;
// 定义所有步骤
this.steps = [
{ id: 1, name: '填写基本信息', method: 'step1_fillBasicInfo' },
{ id: 2, name: '设置密码', method: 'step2_setPassword' },
{ id: 3, name: '邮箱验证', method: 'step3_emailVerification' },
// 根据实际注册流程继续添加
];
}
/**
* 获取步骤总数
*/
getTotalSteps() {
return this.steps.length;
}
/**
* 获取当前步骤信息
*/
getCurrentStepInfo() {
if (this.currentStep === 0) {
return { id: 0, name: '未开始', total: this.getTotalSteps() };
}
const step = this.steps[this.currentStep - 1];
return {
...step,
current: this.currentStep,
total: this.getTotalSteps()
};
}
/**
* 生成账号数据(干运行模式)
*/
generateData(options = {}) {
logger.info(this.siteName, '生成账号数据...');
const account = this.dataGen.generateAccount({
name: options.name,
email: options.email,
username: options.username,
password: options.password,
includePhone: false // Windsurf第一步不需要手机号
});
return account;
}
/**
* 初始化浏览器使用rebrowser-puppeteer自带反检测
*/
async initBrowser() {
// rebrowser-puppeteer 已经打好补丁,无需额外配置
const puppeteer = require('puppeteer');
logger.info(this.siteName, '启动浏览器(反检测模式)...');
// 随机视口大小(模拟不同设备)
const viewports = [
{ width: 1920, height: 1080 },
{ width: 1366, height: 768 },
{ width: 1536, height: 864 },
{ width: 1440, height: 900 }
];
const viewport = viewports[Math.floor(Math.random() * viewports.length)];
this.browser = await puppeteer.launch({
headless: false, // 非无头模式更难被检测
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-blink-features=AutomationControlled',
'--disable-dev-shm-usage',
`--window-size=${viewport.width},${viewport.height}`
],
ignoreDefaultArgs: ['--enable-automation']
});
this.page = await this.browser.newPage();
// 设置随机视口
await this.page.setViewport(viewport);
// 随机用户代理
const userAgents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
];
await this.page.setUserAgent(
userAgents[Math.floor(Math.random() * userAgents.length)]
);
// 设置语言和时区
await this.page.setExtraHTTPHeaders({
'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'
});
logger.success(this.siteName, `浏览器启动成功 (${viewport.width}x${viewport.height})`);
}
/**
* 关闭浏览器
*/
async closeBrowser() {
if (this.browser) {
await this.browser.close();
logger.info(this.siteName, '浏览器已关闭');
}
}
/**
* 步骤1: 填写基本信息First Name, Last Name, Email- 使用人类行为
*/
async step1_fillBasicInfo() {
logger.info(this.siteName, `[步骤 1/${this.getTotalSteps()}] 填写基本信息`);
// 打开注册页面
logger.info(this.siteName, `打开注册页面: ${this.siteUrl}`);
await this.page.goto(this.siteUrl, {
waitUntil: 'networkidle2',
timeout: 30000
});
// 模拟阅读页面1-3秒
await this.human.readPage(1, 3);
// 填写First Name使用人类行为
logger.info(this.siteName, ' → 填写First Name...');
await this.page.waitForSelector('#firstName', { timeout: 10000 });
await this.human.humanType(this.page, '#firstName', this.accountData.firstName);
// 填写Last Name
logger.info(this.siteName, ' → 填写Last Name...');
await this.page.waitForSelector('#lastName', { timeout: 10000 });
await this.human.humanType(this.page, '#lastName', this.accountData.lastName);
// 填写Email
logger.info(this.siteName, ' → 填写Email...');
await this.page.waitForSelector('#email', { timeout: 10000 });
await this.human.humanType(this.page, '#email', this.accountData.email);
// 勾选同意条款(如果有)
try {
const checkbox = await this.page.$('input[type="checkbox"]');
if (checkbox) {
logger.info(this.siteName, ' → 勾选同意条款...');
await this.human.humanCheckbox(this.page, 'input[type="checkbox"]');
}
} catch (error) {
logger.warn(this.siteName, ' → 未找到同意条款checkbox跳过');
}
// 点击Continue按钮使用人类行为
logger.info(this.siteName, ' → 点击Continue按钮...');
// 尝试查找按钮
let buttonSelector = null;
const possibleSelectors = [
'button:has-text("Continue")',
'button[type="submit"]',
'button.continue-button',
'button[class*="continue"]'
];
for (const selector of possibleSelectors) {
try {
const button = await this.page.$(selector);
if (button) {
buttonSelector = selector;
break;
}
} catch (e) {
// 继续尝试下一个
}
}
if (buttonSelector) {
await this.human.visualSearch(this.page, buttonSelector);
await this.human.humanClick(this.page, buttonSelector);
} else {
logger.warn(this.siteName, ' → 未找到Continue按钮尝试按Enter键');
await this.human.randomDelay(500, 1000);
await this.page.keyboard.press('Enter');
}
// 等待跳转或响应
await this.human.randomDelay(2000, 4000);
this.currentStep = 1;
logger.success(this.siteName, `步骤 1 完成`);
}
/**
* 步骤2: 设置密码
*/
async step2_setPassword() {
logger.info(this.siteName, `[步骤 2/${this.getTotalSteps()}] 设置密码`);
// 等待密码页面加载
await this.human.readPage(1, 2);
// 填写密码
logger.info(this.siteName, ' → 填写密码...');
await this.page.waitForSelector('#password', { timeout: 10000 });
await this.human.humanType(this.page, '#password', this.accountData.password);
// 填写确认密码
logger.info(this.siteName, ' → 填写确认密码...');
await this.page.waitForSelector('#passwordConfirmation', { timeout: 10000 });
await this.human.humanType(this.page, '#passwordConfirmation', this.accountData.password);
// 查找并点击Continue按钮
logger.info(this.siteName, ' → 点击Continue按钮...');
const possibleSelectors = [
'button:has-text("Continue")',
'button[type="submit"]',
'button.continue-button',
'button[class*="continue"]'
];
let buttonSelector = null;
for (const selector of possibleSelectors) {
try {
const button = await this.page.$(selector);
if (button) {
buttonSelector = selector;
break;
}
} catch (e) {
// 继续尝试
}
}
if (buttonSelector) {
await this.human.visualSearch(this.page, buttonSelector);
await this.human.humanClick(this.page, buttonSelector);
} else {
logger.warn(this.siteName, ' → 未找到Continue按钮尝试按Enter键');
await this.human.randomDelay(500, 1000);
await this.page.keyboard.press('Enter');
}
// 等待跳转或响应
await this.human.randomDelay(2000, 4000);
this.currentStep = 2;
logger.success(this.siteName, `步骤 2 完成`);
}
/**
* 步骤3: 邮箱验证(待实现)
*/
async step3_emailVerification() {
logger.info(this.siteName, `[步骤 3/${this.getTotalSteps()}] 邮箱验证`);
// 邮箱验证逻辑
// ...
this.currentStep = 3;
logger.warn(this.siteName, '步骤 3 待实现(需要邮箱验证码)');
}
/**
* 执行注册流程
* @param {Object} options - 选项
* @param {number} options.fromStep - 从第几步开始默认1
* @param {number} options.toStep - 执行到第几步(默认全部)
*/
async register(options = {}) {
const fromStep = options.fromStep || 1;
const toStep = options.toStep || this.getTotalSteps();
try {
// 1. 生成数据
this.accountData = this.generateData(options);
logger.success(this.siteName, '账号数据生成完成');
logger.info(this.siteName, `First Name: ${this.accountData.firstName}`);
logger.info(this.siteName, `Last Name: ${this.accountData.lastName}`);
logger.info(this.siteName, `Email: ${this.accountData.email}`);
logger.info(this.siteName, `Password: ${this.accountData.password}`);
// 2. 初始化浏览器
await this.initBrowser();
// 3. 执行指定范围的步骤
logger.info(this.siteName, `\n开始执行步骤 ${fromStep}${toStep} (共 ${this.getTotalSteps()} 步)\n`);
for (let i = fromStep; i <= toStep && i <= this.getTotalSteps(); i++) {
const step = this.steps[i - 1];
if (typeof this[step.method] === 'function') {
try {
await this[step.method]();
} catch (error) {
logger.error(this.siteName, `步骤 ${i} 执行失败: ${error.message}`);
throw error;
}
} else {
logger.warn(this.siteName, `步骤 ${i} (${step.name}) 未实现`);
break;
}
}
const stepInfo = this.getCurrentStepInfo();
logger.success(this.siteName, `\n已完成步骤 ${fromStep}${this.currentStep}`);
if (this.currentStep < this.getTotalSteps()) {
logger.info(this.siteName, `剩余步骤需要手动完成或等待后续开发`);
}
// 不自动关闭浏览器,让用户查看结果
if (!options.keepBrowserOpen) {
logger.info(this.siteName, '10秒后关闭浏览器...');
await this.page.waitForTimeout(10000);
await this.closeBrowser();
} else {
logger.info(this.siteName, '浏览器保持打开状态');
}
return {
success: true,
account: this.accountData,
completedSteps: this.currentStep,
totalSteps: this.getTotalSteps(),
message: `完成 ${this.currentStep}/${this.getTotalSteps()}`
};
} catch (error) {
logger.error(this.siteName, `注册失败: ${error.message}`);
// 截图保存错误状态
if (this.page) {
try {
const screenshotPath = `/tmp/windsurf-error-${Date.now()}.png`;
await this.page.screenshot({ path: screenshotPath });
logger.info(this.siteName, `错误截图已保存: ${screenshotPath}`);
} catch (e) {
// 忽略截图错误
}
}
await this.closeBrowser();
throw error;
}
}
}
module.exports = WindsurfRegister;