A2C工单修复
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* CAPTCHA_PROXY 解析与 Chrome 代理注入(与 CapSolver AntiCloudflareTask 使用同一 IP)
|
||||
*
|
||||
* 仅在实际检测到 CF 挑战、需要 Managed 过盾时由 server.js 显式启用(useCaptchaProxy=true)。
|
||||
* 格式:ip:port:username:password
|
||||
*/
|
||||
const CAPTCHA_PROXY_RAW = (process.env.CAPTCHA_PROXY || '').trim();
|
||||
|
||||
/**
|
||||
* @returns {{
|
||||
* host: string,
|
||||
* port: string,
|
||||
* username: string,
|
||||
* password: string,
|
||||
* chromeProxyServer: string,
|
||||
* capsolverString: string,
|
||||
* }|null}
|
||||
*/
|
||||
function parseCaptchaProxy(raw = CAPTCHA_PROXY_RAW) {
|
||||
const value = (raw || '').trim();
|
||||
if (value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts = value.split(':');
|
||||
if (parts.length < 4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const host = parts[0];
|
||||
const port = parts[1];
|
||||
const username = parts[2];
|
||||
const password = parts.slice(3).join(':');
|
||||
|
||||
if (!host || !port || !username || !password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
chromeProxyServer: `http://${host}:${port}`,
|
||||
capsolverString: value,
|
||||
};
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
function hasCaptchaProxy() {
|
||||
return parseCaptchaProxy() !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否属于可能走 CapSolver Managed 的工单(A2C 等)
|
||||
* 注意:仅表示候选,不代表本次任务一定挂代理
|
||||
* @param {object|null|undefined} antiBot
|
||||
*/
|
||||
function isManagedCfCandidate(antiBot) {
|
||||
if (!antiBot?.enabled) {
|
||||
return false;
|
||||
}
|
||||
if (antiBot.cfChallengeMode === 'managed') {
|
||||
return true;
|
||||
}
|
||||
if (antiBot.cfCloudflareSolver === true) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 请使用 isManagedCfCandidate + 显式 useCaptchaProxy 参数
|
||||
*/
|
||||
function shouldUseCaptchaProxyForAntiBot(antiBot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chrome 启动参数 --proxy-server(须 useCaptchaProxy=true 时调用)
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getCaptchaProxyChromeArgs() {
|
||||
const parsed = parseCaptchaProxy();
|
||||
if (!parsed) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
`--proxy-server=${parsed.chromeProxyServer}`,
|
||||
'--proxy-bypass-list=<-loopback>,localhost,127.0.0.1',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 Page 设置代理认证(须配合 --proxy-server)
|
||||
* @param {import('puppeteer').Page} page
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function applyCaptchaProxyToPage(page) {
|
||||
const parsed = parseCaptchaProxy();
|
||||
if (!parsed || !page) {
|
||||
return false;
|
||||
}
|
||||
await page.authenticate({
|
||||
username: parsed.username,
|
||||
password: parsed.password,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseCaptchaProxy,
|
||||
hasCaptchaProxy,
|
||||
isManagedCfCandidate,
|
||||
shouldUseCaptchaProxyForAntiBot,
|
||||
getCaptchaProxyChromeArgs,
|
||||
applyCaptchaProxyToPage,
|
||||
};
|
||||
Reference in New Issue
Block a user