119 lines
2.8 KiB
JavaScript
Executable File
119 lines
2.8 KiB
JavaScript
Executable File
/**
|
||
* 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,
|
||
};
|