refactor: remove VLESS/Xray, Hy2-only stack
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+4
-50
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user