refactor: remove VLESS/Xray, Hy2-only stack

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-28 00:26:18 +08:00
parent c2c8ae826d
commit 6a42f58f5b
27 changed files with 159 additions and 1322 deletions
+4 -50
View File
@@ -1,4 +1,4 @@
"""从 sing-box Clash API 采集节点连接与流量(官方预编译包不含 v2ray_api)"""
"""从 sing-box Clash API 采集节点连接与流量。"""
from __future__ import annotations
import json
@@ -18,15 +18,10 @@ ROOT = Path(os.environ.get("JIEDIAN_ROOT", Path(__file__).resolve().parents[1]))
ENV_FILE = ROOT / ".env"
CLASH_ADDR = "127.0.0.1:9090"
_VLESS_INBOUND = "vless-reality-in"
_XRAY_ACCESS_LOG = Path("/var/log/xray/access.log")
_LOG_USER_RE = re.compile(
r"\[([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\]\s+inbound connection"
)
_LOG_INDEX_RE = re.compile(r"\[(\d+)\] inbound connection")
_LOG_XRAY_UUID_RE = re.compile(
r"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"
)
_speed_cache: dict[int, tuple[float, int, int]] = {}
_conn_cache: dict[str, dict[str, int | str]] = {}
@@ -76,28 +71,8 @@ def fetch_clash_connections() -> tuple[list[dict], bool]:
return payload.get("connections") or [], True
def fetch_xray_access_uuids(nodes: list[dict]) -> set[str]:
"""VLESS Reality 由 Xray 承载,从 access.log 读取近期活跃 UUID。"""
if not _XRAY_ACCESS_LOG.exists():
return set()
try:
text = _XRAY_ACCESS_LOG.read_text(encoding="utf-8", errors="ignore")
except OSError:
return set()
known = {node["uuid"] for node in nodes}
active: set[str] = set()
for line in text.splitlines()[-400:]:
if "accepted" not in line:
continue
for match in _LOG_XRAY_UUID_RE.finditer(line):
uid = match.group(1)
if uid in known:
active.add(uid)
return active
def fetch_recent_log_uuids(nodes: list[dict]) -> set[str]:
"""sing-box Clash API 不导出 user 字段,VLESS 多用户需从近期日志补全在线 UUID。"""
"""sing-box Clash API 不导出 user 字段,多节点 Hy2 从近期日志补全在线 UUID。"""
try:
proc = subprocess.run(
[
@@ -134,7 +109,6 @@ def fetch_recent_log_uuids(nodes: list[dict]) -> set[str]:
def _global_conn_speed(connections: list[dict]) -> tuple[float, float]:
"""从 /connections 汇总字节增量估算全局速率(/traffic 为 WebSocket 流,不能同步 HTTP 读)。"""
total_up = sum(int(c.get("upload") or 0) for c in connections)
total_down = sum(int(c.get("download") or 0) for c in connections)
now = time.time()
@@ -193,17 +167,6 @@ def _match_connection(conn: dict, node: dict, *, single_node: bool = False) -> b
return False
def _match_vless_connection(conn: dict, node: dict, log_active: set[str]) -> bool:
tag = _connection_inbound_tag(conn)
if tag != _VLESS_INBOUND:
return False
user = _connection_user(conn)
if user == node["uuid"]:
return True
# 共享 VLESS inbound 无法从 Clash API 区分用户;仅唯一活跃用户时归因
return node["uuid"] in log_active and len(log_active) == 1
def _connection_id(conn: dict) -> str:
return str(conn.get("id") or "")
@@ -265,9 +228,7 @@ def _sync_connections(
connections: list[dict],
nodes: list[dict],
uuid_to_node: dict[str, int],
log_active: set[str],
) -> dict[str, tuple[int, int]]:
"""同步连接缓存,断开连接时写入累计流量,返回各用户当前活跃会话流量。"""
seen: set[str] = set()
active: dict[str, tuple[int, int]] = {}
single_node = len(nodes) == 1
@@ -276,9 +237,7 @@ def _sync_connections(
for conn in connections:
matched_uuid = ""
for node in nodes:
if _match_connection(conn, node, single_node=single_node) or _match_vless_connection(
conn, node, log_active
):
if _match_connection(conn, node, single_node=single_node):
matched_uuid = node["uuid"]
break
if not matched_uuid and single_node and connections:
@@ -346,7 +305,6 @@ def _connections_for_node(
c
for c in connections
if _match_connection(c, node, single_node=single_node)
or _match_vless_connection(c, node, log_active)
]
if matched:
return matched
@@ -355,9 +313,6 @@ def _connections_for_node(
return connections
if node["uuid"] in log_active:
vless_hits = [c for c in connections if _connection_inbound_tag(c) == _VLESS_INBOUND]
if vless_hits:
return vless_hits
return [None]
return []
@@ -367,8 +322,7 @@ def collect_node_stats() -> dict:
uuid_to_node = {node["uuid"]: int(node["id"]) for node in nodes}
connections, clash_ok = fetch_clash_connections()
log_active = fetch_recent_log_uuids(nodes) if len(nodes) > 1 else set()
log_active |= fetch_xray_access_uuids(nodes)
active_by_uuid = _sync_connections(connections, nodes, uuid_to_node, log_active)
active_by_uuid = _sync_connections(connections, nodes, uuid_to_node)
single_node = len(nodes) == 1
has_connections = len(connections) > 0
global_up_speed, global_down_speed = _global_conn_speed(connections) if clash_ok else (0.0, 0.0)