60 lines
1.8 KiB
Python
60 lines
1.8 KiB
Python
import os
|
||
from enum import Enum, auto
|
||
from dataclasses import dataclass, field
|
||
|
||
|
||
class ProxyType(Enum):
|
||
HTTP = auto()
|
||
HTTPS = auto()
|
||
SOCKS = auto()
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class ProxyInfo:
|
||
ip: str = field(default="", repr=True)
|
||
port: str = field(default="", repr=True)
|
||
|
||
def __post_init__(self):
|
||
if (self.ip and not self.port) or (not self.ip and self.port):
|
||
raise ValueError("IP or port cannot be empty")
|
||
|
||
if (self.ip and self.port) and (not self.port.isdigit() or not (1 <= int(self.port) <= 65535)):
|
||
raise ValueError("Port must be a digit between 1 and 65535")
|
||
|
||
|
||
class ProxyDetector:
|
||
"""仅 Linux:从环境变量读取代理(http_proxy / https_proxy / ftp_proxy)。"""
|
||
|
||
def get_proxy_info(self) -> ProxyInfo:
|
||
ip, port = self._get_proxy_info_linux()
|
||
return ProxyInfo(ip, port)
|
||
|
||
def is_proxy_enabled(self) -> bool:
|
||
return self._is_proxy_enabled_linux()
|
||
|
||
@staticmethod
|
||
def _get_proxy_info_linux() -> tuple[str, str]:
|
||
proxies = {
|
||
"http": os.getenv("http_proxy"),
|
||
"https": os.getenv("https_proxy"),
|
||
"ftp": os.getenv("ftp_proxy"),
|
||
}
|
||
ip = port = ""
|
||
for _proto, proxy in proxies.items():
|
||
if proxy:
|
||
# 支持 http://host:port
|
||
p = proxy.strip()
|
||
if "://" in p:
|
||
p = p.split("://", 1)[1]
|
||
if "@" in p:
|
||
p = p.split("@", 1)[1]
|
||
if ":" in p:
|
||
ip, _, port = p.rpartition(":")
|
||
port = port.split("/")[0]
|
||
break
|
||
return ip, port
|
||
|
||
def _is_proxy_enabled_linux(self) -> bool:
|
||
ip, port = self._get_proxy_info_linux()
|
||
return bool(ip and port)
|