mirror of
https://github.com/baoweise-bot/aimili-vpngate.git
synced 2026-09-07 00:36:49 +08:00
feat: optimize node fetching with conditional retries and implement post-connection proxy health checks and UI status updates
This commit is contained in:
+13
-1
@@ -359,9 +359,18 @@ def print_status():
|
||||
connecting_msg = state.get('last_check_message') or '正在建立加密隧道并验证路由规则...'
|
||||
print_line(format_line("节点状态", f"{yellow}{connecting_msg}{reset}"))
|
||||
elif active_ip:
|
||||
print_line(format_line("节点 IP", active_ip))
|
||||
proxy_ip = state.get("proxy_ip", "-")
|
||||
proxy_latency = state.get("proxy_latency_ms", 0)
|
||||
proxy_ok = state.get("proxy_ok", False)
|
||||
|
||||
print_line(format_line("节点 IP (入口)", active_ip))
|
||||
print_line(format_line("节点地区", active_loc))
|
||||
print_line(format_line("节点延迟 (直连测试)", latency))
|
||||
if proxy_ok and proxy_ip and proxy_ip != "-":
|
||||
print_line(format_line("出口 IP (出站)", proxy_ip))
|
||||
print_line(format_line("本地代理延迟", f"{proxy_latency} ms" if proxy_latency else "检测中..."))
|
||||
else:
|
||||
print_line(format_line("出口 IP (出站)", f"{red}[检测中/未就绪]{reset}"))
|
||||
else:
|
||||
print_line(format_line("节点状态", "无活动连接"))
|
||||
print_line()
|
||||
@@ -652,6 +661,9 @@ def get_status_state():
|
||||
state.get("active_openvpn_node_id", ""),
|
||||
state.get("last_check_message", ""),
|
||||
state.get("active_node_latency", ""),
|
||||
state.get("proxy_ip", "-"),
|
||||
state.get("proxy_latency_ms", 0),
|
||||
state.get("proxy_ok", False),
|
||||
check_port_listening(7928),
|
||||
check_service_active("aimilivpn.service"),
|
||||
check_openvpn_process(),
|
||||
|
||||
+31
-10
@@ -239,7 +239,7 @@ def fetch_api_text() -> str:
|
||||
"Accept": "text/plain,*/*",
|
||||
},
|
||||
)
|
||||
with urllib.request.urlopen(request, timeout=45) as response:
|
||||
with urllib.request.urlopen(request, timeout=12) as response:
|
||||
return response.read().decode("utf-8", errors="replace")
|
||||
|
||||
def parse_vpngate_rows(text: str) -> list[dict[str, str]]:
|
||||
@@ -299,8 +299,12 @@ def fetch_candidates() -> list[dict[str, Any]]:
|
||||
candidates: list[dict[str, Any]] = []
|
||||
seen_ips = set()
|
||||
|
||||
log_to_json("INFO", "Main", "开始拉取官方 API 节点列表...")
|
||||
for i in range(3):
|
||||
# 检查本地是否有节点缓存,以确定最大重试尝试次数
|
||||
has_cache = len(cached_nodes()) > 0
|
||||
max_attempts = 1 if has_cache else 2
|
||||
|
||||
log_to_json("INFO", "Main", f"开始拉取官方 API 节点列表 (最大尝试次数: {max_attempts})...")
|
||||
for i in range(max_attempts):
|
||||
if i > 0:
|
||||
time.sleep(1.5)
|
||||
try:
|
||||
@@ -320,7 +324,7 @@ def fetch_candidates() -> list[dict[str, Any]]:
|
||||
except Exception as e:
|
||||
print(f"[fetch_candidates] Fetch {i+1} failed: {e}", flush=True)
|
||||
log_to_json("WARNING", "Main", f"第 {i+1} 次拉取 API 节点失败: {e}")
|
||||
if i == 0 and not candidates:
|
||||
if i == max_attempts - 1 and not candidates:
|
||||
log_to_json("ERROR", "Main", f"获取官方 API 节点失败: {e}")
|
||||
raise
|
||||
|
||||
@@ -819,6 +823,7 @@ def connect_node(node_id: str) -> str:
|
||||
print("[连接] 正在建立其他连接中,跳过此请求", flush=True)
|
||||
return "Already connecting"
|
||||
is_connecting = True
|
||||
active_openvpn_node_id = node_id
|
||||
set_state(active_openvpn_node_id=node_id, is_connecting=True, active_node_latency="正在连接", last_check_message="正在初始化连接配置...")
|
||||
|
||||
try:
|
||||
@@ -854,6 +859,8 @@ def connect_node(node_id: str) -> str:
|
||||
write_json(NODES_FILE, nodes)
|
||||
log_to_json("ERROR", "VPN", f"连接节点 {node_id} 失败: {message}")
|
||||
set_state(active_openvpn_node_id="", is_connecting=False, active_node_latency="无活动连接", last_check_message=f"连接失败: {message}")
|
||||
with lock:
|
||||
active_openvpn_node_id = ""
|
||||
raise RuntimeError(message)
|
||||
|
||||
active_openvpn_process = process
|
||||
@@ -882,6 +889,24 @@ def connect_node(node_id: str) -> str:
|
||||
if item["active"]:
|
||||
item["probe_message"] = f"Active node. HTTP proxy: http://{LOCAL_PROXY_HOST}:{LOCAL_PROXY_PORT}"
|
||||
write_json(NODES_FILE, nodes)
|
||||
|
||||
set_state(last_check_message="正在测试本地代理出站联通性与出口 IP...")
|
||||
res = check_proxy_health()
|
||||
if res["ok"]:
|
||||
set_state(
|
||||
proxy_ok=True,
|
||||
proxy_ip=res["ip"],
|
||||
proxy_latency_ms=res["latency_ms"],
|
||||
proxy_error=""
|
||||
)
|
||||
else:
|
||||
set_state(
|
||||
proxy_ok=False,
|
||||
proxy_ip="-",
|
||||
proxy_latency_ms=0,
|
||||
proxy_error=res.get("error", "未知错误")
|
||||
)
|
||||
|
||||
latency_str = f"{last_active_latency} ms" if last_active_latency > 0 else "检测超时"
|
||||
set_state(active_openvpn_node_id=node_id, is_connecting=False, last_check_message=f"Connected {node_id}", active_node_latency=latency_str)
|
||||
log_to_json("INFO", "VPN", f"节点 {node_id} 连接成功,出口网卡 tun0 已启用")
|
||||
@@ -915,12 +940,8 @@ def maintain_valid_nodes(force: bool = False) -> str:
|
||||
candidates = fetch_candidates()
|
||||
except Exception as exc:
|
||||
vpn_utils.check_and_fix_dns()
|
||||
try:
|
||||
set_state(is_connecting=True, last_check_message="解析失败重试:正在拉取最新的免费 VPN 节点列表...")
|
||||
candidates = fetch_candidates()
|
||||
except Exception as exc2:
|
||||
set_state(last_fetch_at=time.time(), last_fetch_status="error", last_fetch_message=str(exc2))
|
||||
candidates = []
|
||||
set_state(last_fetch_at=time.time(), last_fetch_status="error", last_fetch_message=str(exc))
|
||||
candidates = []
|
||||
|
||||
if not candidates:
|
||||
is_connecting = False
|
||||
|
||||
Reference in New Issue
Block a user