UNPKG

rsshub

Version:
335 lines (330 loc) • 12.9 kB
import { t as config } from "./config-C37vj7VH.mjs"; import { t as logger_default } from "./logger-Czu8UMNd.mjs"; import { ProxyAgent } from "undici"; import { HttpsProxyAgent } from "https-proxy-agent"; import { PacProxyAgent } from "pac-proxy-agent"; import { SocksProxyAgent } from "socks-proxy-agent"; //#region lib/utils/proxy/unify-proxy.ts const defaultProtocol = "http"; const possibleProtocol$1 = [ "http", "https", "socks", "socks4", "socks4a", "socks5", "socks5h" ]; const unifyProxy = (proxyUri$1, proxyObj$1) => { proxyObj$1 = proxyObj$1 || {}; const [oriProxyUri, oriProxyObj] = [proxyUri$1, proxyObj$1]; proxyObj$1 = { ...proxyObj$1 }; let proxyUrlHandler$1 = null; if (proxyUri$1 && typeof proxyUri$1 === "string") { if (!proxyUri$1.includes("://")) { logger_default.warn(`PROXY_URI contains no protocol, assuming ${defaultProtocol}`); proxyUri$1 = `${defaultProtocol}://${proxyUri$1}`; } try { proxyUrlHandler$1 = new URL(proxyUri$1); } catch (error) { logger_default.error(`Parse PROXY_URI error: ${error.stack}`); } } if (proxyObj$1.protocol || proxyObj$1.host || proxyObj$1.port) if (proxyUrlHandler$1) logger_default.warn("PROXY_URI is set, ignoring PROXY_{PROTOCOL,HOST,PORT}"); else if (proxyObj$1.host) { let tempProxyStr = proxyObj$1.host; if (tempProxyStr.includes("://")) logger_default.warn("PROXY_HOST contains protocol, ignoring PROXY_PROTOCOL"); else if (proxyObj$1.protocol) tempProxyStr = `${proxyObj$1.protocol}://${tempProxyStr}`; else { logger_default.warn(`PROXY_PROTOCOL is not set, assuming '${defaultProtocol}'`); tempProxyStr = `${defaultProtocol}://${tempProxyStr}`; } try { proxyUrlHandler$1 = new URL(tempProxyStr); if (proxyUrlHandler$1.port && proxyObj$1.port) logger_default.warn("PROXY_HOST contains port, ignoring PROXY_PORT"); else if (proxyObj$1.port) if (Number.parseInt(proxyObj$1.port)) proxyUrlHandler$1.port = proxyObj$1.port; else logger_default.warn(`PROXY_PORT is not a number, ignoring`); else logger_default.warn("PROXY_PORT is not set, leaving proxy agent to determine"); } catch (error) { logger_default.error(`Parse PROXY_HOST error: ${error.stack}`); } } else logger_default.warn("Either PROXY_{PROTOCOL,PORT} is set, but PROXY_HOST is missing, ignoring"); if (proxyObj$1.auth && proxyUrlHandler$1) { let promptProxyUri = false; if (proxyUrlHandler$1.username || proxyUrlHandler$1.password) { logger_default.warn("PROXY_URI contains username and/or password, ignoring PROXY_AUTH"); proxyObj$1.auth = void 0; } else if (["http:", "https:"].includes(proxyUrlHandler$1.protocol)) { logger_default.info("PROXY_AUTH is set and will be used for requests from Node.js. However, requests from puppeteer will not use it"); promptProxyUri = true; } else { logger_default.warn(`PROXY_AUTH is only supported by HTTP(S) proxies, but got ${proxyUrlHandler$1.protocol}, ignoring`); proxyObj$1.auth = void 0; promptProxyUri = true; } if (promptProxyUri) logger_default.info("To get rid of this, set PROXY_URI like protocol://username:password@host:port and clear PROXY_{AUTH,PROTOCOL,HOST,PORT}"); } let isProxyValid = false; if (proxyUrlHandler$1) { const protocol = proxyUrlHandler$1.protocol.replace(":", ""); if (possibleProtocol$1.includes(protocol)) { if (protocol !== "http" && (proxyUrlHandler$1.username || proxyUrlHandler$1.password)) { logger_default.warn("PROXY_URI is an HTTPS/SOCKS proxy with authentication, which is not supported by puppeteer (ignore if you don't need it)"); logger_default.info("To get rid of this, consider using an HTTP proxy instead"); } proxyObj$1.protocol = protocol; proxyObj$1.host = proxyUrlHandler$1.hostname; proxyObj$1.port = proxyUrlHandler$1.port || void 0; proxyUri$1 = proxyUrlHandler$1.href.endsWith("/") ? proxyUrlHandler$1.href.slice(0, -1) : proxyUrlHandler$1.href; isProxyValid = true; } else logger_default.error(`Unsupported proxy protocol: ${protocol}, expect one of ${possibleProtocol$1.join(", ")}`); } if (!isProxyValid) { if (oriProxyUri && typeof oriProxyUri === "string" || oriProxyObj.protocol || oriProxyObj.host || oriProxyObj.port || oriProxyObj.auth) logger_default.error("Proxy is disabled due to misconfiguration"); proxyObj$1.protocol = proxyObj$1.host = proxyObj$1.port = proxyObj$1.auth = void 0; proxyUri$1 = void 0; proxyUrlHandler$1 = null; } return { proxyUri: proxyUri$1, proxyObj: proxyObj$1, proxyUrlHandler: proxyUrlHandler$1 }; }; var unify_proxy_default = unifyProxy; //#endregion //#region lib/utils/proxy/multi-proxy.ts const createMultiProxy = (proxyUris, proxyObj$1) => { const proxies = []; let currentProxyIndex = 0; for (const uri of proxyUris) { const unifiedProxy = unify_proxy_default(uri, proxyObj$1); if (unifiedProxy.proxyUri) proxies.push({ uri: unifiedProxy.proxyUri, isActive: true, failureCount: 0, urlHandler: unifiedProxy.proxyUrlHandler }); } if (proxies.length === 0) { logger_default.warn("No valid proxies found in the provided list"); return { allProxies: [], proxyObj: proxyObj$1 || {}, getNextProxy: () => null, markProxyFailed: () => {}, resetProxy: () => {} }; } const healthCheckInterval = proxyObj$1?.healthCheckInterval || 6e4; const maxFailures = 3; const healthCheck = () => { const now = Date.now(); for (const proxy of proxies) if (!proxy.isActive && proxy.lastFailureTime && now - proxy.lastFailureTime > healthCheckInterval) { proxy.isActive = true; proxy.failureCount = 0; delete proxy.lastFailureTime; logger_default.info(`Proxy ${proxy.uri} marked as active again after health check`); } }; setInterval(healthCheck, healthCheckInterval); const getNextProxy = () => { const activeProxies = proxies.filter((p) => p.isActive); if (activeProxies.length === 0) { logger_default.warn("No active proxies available"); return null; } let nextProxy = activeProxies[currentProxyIndex % activeProxies.length]; let attempts = 0; while (!nextProxy.isActive && attempts < activeProxies.length) { currentProxyIndex = (currentProxyIndex + 1) % activeProxies.length; nextProxy = activeProxies[currentProxyIndex]; attempts++; } if (!nextProxy.isActive) return null; return nextProxy; }; const markProxyFailed$1 = (proxyUri$1) => { const proxy = proxies.find((p) => p.uri === proxyUri$1); if (proxy) { proxy.failureCount++; proxy.lastFailureTime = Date.now(); if (proxy.failureCount >= maxFailures) { proxy.isActive = false; logger_default.warn(`Proxy ${proxyUri$1} marked as inactive after ${maxFailures} failures`); } else logger_default.warn(`Proxy ${proxyUri$1} failed (${proxy.failureCount}/${maxFailures})`); const activeProxies = proxies.filter((p) => p.isActive); if (activeProxies.length > 0) { currentProxyIndex = (currentProxyIndex + 1) % activeProxies.length; const nextProxy = getNextProxy(); if (nextProxy) logger_default.info(`Switching to proxy: ${nextProxy.uri}`); } } }; const resetProxy = (proxyUri$1) => { const proxy = proxies.find((p) => p.uri === proxyUri$1); if (proxy) { proxy.isActive = true; proxy.failureCount = 0; delete proxy.lastFailureTime; logger_default.info(`Proxy ${proxyUri$1} manually reset`); } }; const currentProxy = getNextProxy(); if (currentProxy) logger_default.info(`Initial proxy selected: ${currentProxy.uri}`); return { currentProxy, allProxies: proxies, proxyObj: proxyObj$1 || {}, getNextProxy, markProxyFailed: markProxyFailed$1, resetProxy }; }; var multi_proxy_default = createMultiProxy; //#endregion //#region lib/utils/proxy/pac-proxy.ts const possibleProtocol = [ "http", "https", "ftp", "file", "data" ]; const pacProxy = (pacUri, pacScript, proxyObj$1) => { let pacUrlHandler = null; if (pacScript) if (typeof pacScript === "string") pacUri = "data:text/javascript;charset=utf-8," + encodeURIComponent(pacScript); else logger_default.error("Invalid PAC_SCRIPT, use PAC_URI instead"); if (pacUri && typeof pacUri === "string") try { pacUrlHandler = new URL(pacUri); } catch (error) { pacUri = void 0; pacUrlHandler = null; logger_default.error(`Parse PAC_URI error: ${error.stack}`); } else pacUri = void 0; if (pacUri && (!pacUrlHandler?.protocol || !possibleProtocol.includes(pacUrlHandler.protocol.replace(":", "")))) { logger_default.error(`Unsupported PAC protocol: ${pacUrlHandler?.protocol?.replace(":", "")}, expect one of ${possibleProtocol.join(", ")}`); pacUri = void 0; pacUrlHandler = null; } if (pacUrlHandler) { proxyObj$1.host = pacUrlHandler.hostname; proxyObj$1.port = pacUrlHandler.port; proxyObj$1.protocol = pacUrlHandler.protocol.replace(":", ""); } else proxyObj$1.protocol = proxyObj$1.host = proxyObj$1.port = proxyObj$1.auth = void 0; if (proxyObj$1.auth && pacUrlHandler) { let promptProxyUri = false; if (pacUrlHandler.username || pacUrlHandler.password) { logger_default.warn("PAC_URI contains username and/or password, ignoring PROXY_AUTH"); proxyObj$1.auth = void 0; } else if (["http:", "https:"].includes(pacUrlHandler.protocol)) { logger_default.info("PROXY_AUTH is set and will be used for requests from Node.js. However, requests from puppeteer will not use it"); promptProxyUri = true; } else { logger_default.warn(`PROXY_AUTH is only supported by HTTP(S) proxies, but got ${pacUrlHandler.protocol}, ignoring`); proxyObj$1.auth = void 0; promptProxyUri = true; } if (promptProxyUri) logger_default.info("To get rid of this, set PAC_URI like protocol://username:password@host:port and clear PROXY_{AUTH,PROTOCOL,HOST,PORT}"); } return { proxyUri: pacUri, proxyObj: proxyObj$1, proxyUrlHandler: pacUrlHandler }; }; var pac_proxy_default = pacProxy; //#endregion //#region lib/utils/proxy/index.ts const proxyIsPAC = config.pacUri || config.pacScript; let proxyUri; let proxyObj = {}; let proxyUrlHandler = null; let multiProxy; const createAgentForProxy = (uri, proxyObj$1) => { if (uri.startsWith("http")) return new HttpsProxyAgent(uri, { headers: { "proxy-authorization": proxyObj$1?.auth ? `Basic ${proxyObj$1.auth}` : void 0 } }); else if (uri.startsWith("socks")) return new SocksProxyAgent(uri); return null; }; const createDispatcherForProxy = (uri, proxyObj$1) => { if (uri.startsWith("http")) return new ProxyAgent({ uri, token: proxyObj$1?.auth ? `Basic ${proxyObj$1.auth}` : void 0, requestTls: { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" } }); return null; }; if (proxyIsPAC) { const proxy = pac_proxy_default(config.pacUri, config.pacScript, config.proxy); proxyUri = proxy.proxyUri; proxyObj = proxy.proxyObj; proxyUrlHandler = proxy.proxyUrlHandler; } else if (config.proxyUris && config.proxyUris.length > 0) { multiProxy = multi_proxy_default(config.proxyUris, config.proxy); proxyObj = multiProxy.proxyObj; const currentProxy = multiProxy.getNextProxy(); if (currentProxy) { proxyUri = currentProxy.uri; proxyUrlHandler = currentProxy.urlHandler; } logger_default.info(`Multi-proxy initialized with ${config.proxyUris.length} proxies`); } else { const proxy = unify_proxy_default(config.proxyUri, config.proxy); proxyUri = proxy.proxyUri; proxyObj = proxy.proxyObj; proxyUrlHandler = proxy.proxyUrlHandler; } let agent = null; let dispatcher = null; if (proxyIsPAC && proxyUri) agent = new PacProxyAgent(`pac+${proxyUri}`); else if (proxyUri) { agent = createAgentForProxy(proxyUri, proxyObj); dispatcher = createDispatcherForProxy(proxyUri, proxyObj); } const getCurrentProxy = () => { if (multiProxy) return multiProxy.getNextProxy(); if (proxyUri) return { uri: proxyUri, isActive: true, failureCount: 0, urlHandler: proxyUrlHandler }; return null; }; const markProxyFailed = (failedProxyUri) => { if (multiProxy) { multiProxy.markProxyFailed(failedProxyUri); const nextProxy = multiProxy.getNextProxy(); if (nextProxy) { proxyUri = nextProxy.uri; proxyUrlHandler = nextProxy.urlHandler || null; agent = createAgentForProxy(nextProxy.uri, proxyObj); dispatcher = createDispatcherForProxy(nextProxy.uri, proxyObj); logger_default.info(`Switched to proxy: ${nextProxy.uri}`); } else { logger_default.warn("No available proxies remaining"); agent = null; dispatcher = null; proxyUri = void 0; } } }; const getAgentForProxy = (proxyState) => createAgentForProxy(proxyState.uri, proxyObj); const getDispatcherForProxy = (proxyState) => createDispatcherForProxy(proxyState.uri, proxyObj); const proxyExport = { agent, dispatcher, proxyUri, proxyObj, proxyUrlHandler, multiProxy, getCurrentProxy, markProxyFailed, getAgentForProxy, getDispatcherForProxy }; var proxy_default = proxyExport; //#endregion export { proxy_default as t };