rsshub
Version:
Make RSS Great Again!
335 lines (330 loc) • 12.9 kB
JavaScript
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 };