dasdasd
This commit is contained in:
parent
313be582c0
commit
223c85d01a
@ -764,52 +764,201 @@ class WindsurfRegister {
|
||||
|
||||
logger.info(this.siteName, `[CapSolver] 调试信息: ${JSON.stringify(debugInfo)}`);
|
||||
|
||||
// 3. 注入 token(完全按照 CapSolver 官方文档)
|
||||
// 3. 注入 token 到页面
|
||||
logger.info(this.siteName, '[CapSolver] 等待 input 元素...');
|
||||
await this.page.waitForSelector('input[name="cf-turnstile-response"]', { timeout: 10000 });
|
||||
|
||||
logger.info(this.siteName, '[CapSolver] 注入 token 到页面...');
|
||||
await this.page.evaluate((solution) => {
|
||||
document.querySelector('input[name="cf-turnstile-response"]').value = solution;
|
||||
logger.info(this.siteName, `[CapSolver] 注入 token 到页面 (长度: ${token.length})...`);
|
||||
|
||||
// 步骤1: 注入 token 并触发事件
|
||||
await this.page.evaluate((token) => {
|
||||
const input = document.querySelector('input[name="cf-turnstile-response"]');
|
||||
if (input) {
|
||||
input.value = token;
|
||||
// 触发各种事件以通知页面
|
||||
['input', 'change', 'blur'].forEach(eventType => {
|
||||
input.dispatchEvent(new Event(eventType, { bubbles: true }));
|
||||
});
|
||||
}
|
||||
}, token);
|
||||
|
||||
logger.success(this.siteName, '[CapSolver] ✓ Token 已注入到 hidden input');
|
||||
|
||||
// 等待一下让 Turnstile 处理 token
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
// 步骤2: 查找并触发 Turnstile 回调函数
|
||||
logger.info(this.siteName, '[CapSolver] 尝试触发 Turnstile 回调...');
|
||||
|
||||
const callbackResult = await this.page.evaluate((token) => {
|
||||
const results = [];
|
||||
|
||||
// 方法A: 查找 React 组件的回调
|
||||
if (window.cf__reactTurnstileOnLoad && typeof window.cf__reactTurnstileOnLoad === 'function') {
|
||||
try {
|
||||
window.cf__reactTurnstileOnLoad(token);
|
||||
results.push('✓ cf__reactTurnstileOnLoad');
|
||||
} catch (e) {
|
||||
results.push(`✗ cf__reactTurnstileOnLoad: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 方法B: 从 DOM 元素获取回调名称
|
||||
const turnstileDiv = document.querySelector('[data-callback]');
|
||||
if (turnstileDiv) {
|
||||
const callbackName = turnstileDiv.getAttribute('data-callback');
|
||||
if (callbackName && window[callbackName] && typeof window[callbackName] === 'function') {
|
||||
try {
|
||||
window[callbackName](token);
|
||||
results.push(`✓ data-callback: ${callbackName}`);
|
||||
} catch (e) {
|
||||
results.push(`✗ ${callbackName}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 方法C: 使用 turnstile API (如果存在)
|
||||
if (window.turnstile) {
|
||||
if (typeof window.turnstile.reset === 'function') {
|
||||
try {
|
||||
// 查找 widget ID
|
||||
const widgets = document.querySelectorAll('[id^="cf-chl-widget"]');
|
||||
widgets.forEach((widget, index) => {
|
||||
const widgetId = widget.id;
|
||||
try {
|
||||
window.turnstile.reset(widgetId);
|
||||
results.push(`✓ reset widget: ${widgetId}`);
|
||||
} catch (e) {
|
||||
results.push(`✗ reset ${widgetId}: ${e.message}`);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
results.push(`✗ turnstile.reset: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window.turnstile.execute === 'function') {
|
||||
try {
|
||||
window.turnstile.execute();
|
||||
results.push('✓ turnstile.execute()');
|
||||
} catch (e) {
|
||||
results.push(`✗ turnstile.execute: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 方法D: 遍历 window 查找包含 turnstile 的函数
|
||||
for (let key in window) {
|
||||
if (key.toLowerCase().includes('turnstile') &&
|
||||
typeof window[key] === 'function' &&
|
||||
!results.some(r => r.includes(key))) {
|
||||
try {
|
||||
window[key](token);
|
||||
results.push(`✓ window.${key}`);
|
||||
} catch (e) {
|
||||
// 忽略错误,继续尝试
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}, token);
|
||||
|
||||
if (callbackResult.length > 0) {
|
||||
logger.info(this.siteName, `[CapSolver] 回调触发结果:`);
|
||||
callbackResult.forEach(result => {
|
||||
logger.info(this.siteName, ` ${result}`);
|
||||
});
|
||||
} else {
|
||||
logger.warn(this.siteName, '[CapSolver] ⚠️ 未找到任何回调函数');
|
||||
}
|
||||
|
||||
// 等待一下让回调处理
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 步骤3: 强制激活按钮(后备方案)
|
||||
logger.info(this.siteName, '[CapSolver] 检查并激活提交按钮...');
|
||||
|
||||
const buttonActivated = await this.page.evaluate(() => {
|
||||
const buttons = Array.from(document.querySelectorAll('button'));
|
||||
let activated = false;
|
||||
|
||||
buttons.forEach(btn => {
|
||||
if (btn.textContent.trim() === 'Continue' ||
|
||||
btn.textContent.trim() === 'Submit') {
|
||||
if (btn.disabled) {
|
||||
// 移除 disabled 属性
|
||||
btn.disabled = false;
|
||||
btn.removeAttribute('disabled');
|
||||
|
||||
// 移除可能的 disabled class
|
||||
btn.classList.remove('disabled');
|
||||
|
||||
activated = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return activated;
|
||||
});
|
||||
|
||||
if (buttonActivated) {
|
||||
logger.success(this.siteName, '[CapSolver] ✓ 已强制激活按钮');
|
||||
} else {
|
||||
logger.info(this.siteName, '[CapSolver] 按钮已经是激活状态');
|
||||
}
|
||||
|
||||
// 步骤4: 等待验证完成确认
|
||||
logger.info(this.siteName, '[CapSolver] 等待验证完成确认...');
|
||||
|
||||
// 4. 等待 Turnstile 真正完成(检查 iframe checkbox 状态)
|
||||
logger.info(this.siteName, '[CapSolver] 等待 Turnstile 验证完成...');
|
||||
try {
|
||||
await this.page.waitForFunction(
|
||||
() => {
|
||||
// 必须检查 iframe 是否真的显示勾选状态
|
||||
const iframe = document.querySelector('iframe[src*="challenges.cloudflare.com"]');
|
||||
if (!iframe) return false;
|
||||
|
||||
// 检查 iframe 的 data-state 或其他成功标记
|
||||
const iframeSuccess = iframe.getAttribute('data-state') === 'success' ||
|
||||
iframe.getAttribute('data-success') === 'true';
|
||||
|
||||
// 检查按钮是否真的激活了
|
||||
// 检查1: 按钮必须激活
|
||||
const button = document.querySelector('button');
|
||||
const buttonEnabled = button && !button.disabled;
|
||||
const buttonEnabled = button && !button.disabled &&
|
||||
(button.textContent.trim() === 'Continue' ||
|
||||
button.textContent.trim() === 'Submit');
|
||||
|
||||
// 检查 hidden input 是否有值(作为辅助判断)
|
||||
// 检查2: hidden input 必须有值
|
||||
const input = document.querySelector('[name="cf-turnstile-response"]');
|
||||
const hasToken = input && input.value && input.value.length > 0;
|
||||
|
||||
// 必须同时满足:有 token 且按钮激活
|
||||
return hasToken && buttonEnabled;
|
||||
// 检查3: iframe 状态(如果存在)
|
||||
const iframe = document.querySelector('iframe[src*="challenges.cloudflare.com"]');
|
||||
const iframeOk = !iframe ||
|
||||
iframe.getAttribute('data-state') === 'success' ||
|
||||
iframe.getAttribute('data-success') === 'true';
|
||||
|
||||
// 至少满足:按钮激活 + 有token
|
||||
return buttonEnabled && hasToken;
|
||||
},
|
||||
{ timeout: 20000 }
|
||||
{ timeout: 10000, polling: 500 }
|
||||
);
|
||||
logger.success(this.siteName, '[CapSolver] ✓ Turnstile 验证真正完成');
|
||||
|
||||
logger.success(this.siteName, '[CapSolver] ✓ 验证完成确认通过');
|
||||
|
||||
} catch (e) {
|
||||
logger.error(this.siteName, '[CapSolver] Turnstile 验证未完成,可能需要手动操作');
|
||||
// 给用户 30 秒手动点击
|
||||
logger.warn(this.siteName, '[CapSolver] 等待 30 秒供手动点击 checkbox...');
|
||||
await new Promise(resolve => setTimeout(resolve, 30000));
|
||||
logger.warn(this.siteName, '[CapSolver] 验证完成检测超时,但将继续尝试...');
|
||||
|
||||
// 输出调试信息
|
||||
const debugInfo = await this.page.evaluate(() => {
|
||||
const button = document.querySelector('button');
|
||||
const input = document.querySelector('[name="cf-turnstile-response"]');
|
||||
return {
|
||||
buttonDisabled: button?.disabled,
|
||||
buttonText: button?.textContent.trim(),
|
||||
hasToken: !!input?.value,
|
||||
tokenLength: input?.value?.length || 0
|
||||
};
|
||||
});
|
||||
|
||||
logger.info(this.siteName, `[CapSolver] 当前状态: ${JSON.stringify(debugInfo)}`);
|
||||
|
||||
// 如果按钮已激活且有token,认为成功
|
||||
if (!debugInfo.buttonDisabled && debugInfo.hasToken) {
|
||||
logger.success(this.siteName, '[CapSolver] ✓ 状态检查通过,继续执行');
|
||||
} else {
|
||||
logger.warn(this.siteName, '[CapSolver] 等待 10 秒供手动处理...');
|
||||
await new Promise(resolve => setTimeout(resolve, 10000));
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 点击 Continue 按钮
|
||||
|
||||
Loading…
Reference in New Issue
Block a user