zapret-kvn/xray_fluent/diagnostics.py
loop-uh 2a14314be5
All checks were successful
Windows project source guards / test (push) Successful in 3m53s
Prepare v0.4.78: server list rework, faster switching, subscriptions
- Server list on QSortFilterProxyModel with diff updates, batched ping
  results, compact 30px rows, configurable persisted columns and sorting
- Faster node switching: instant kill instead of terminate timeout,
  socket probes instead of netstat, ctypes adapter polling, batched
  route commands, mtime config cache, generator-based hot-swap
  transitions (TransitionRunner)
- Subscriptions: fetch/parse/reconcile services with UI page and QR import

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 22:10:53 +03:00

74 lines
1.8 KiB
Python

from __future__ import annotations
from datetime import datetime, timezone
import json
from pathlib import Path
import platform
import re
import zipfile
from .models import AppState
REDACT_KEYS = {
"id",
"password",
"pass",
"token",
"publickey",
"privatekey",
"private_key",
"secretkey",
"secret_key",
"pre_shared_key",
"presharedkey",
"shortid",
"sid",
"uuid",
"url",
"pending_url",
"web_page_url",
"support_url",
"link",
"auth",
"auth_str",
"username",
}
_URL_RE = re.compile(r"https?://[^\s'\"<>]+", re.IGNORECASE)
def _redact(value):
if isinstance(value, dict):
redacted = {}
for key, item in value.items():
if str(key).casefold() in REDACT_KEYS:
redacted[key] = "***"
else:
redacted[key] = _redact(item)
return redacted
if isinstance(value, list):
return [_redact(item) for item in value]
return value
def _redact_log_line(line: str) -> str:
return _URL_RE.sub("<URL скрыт>", str(line))
def export_diagnostics(zip_path: Path, state: AppState, logs: list[str]) -> Path:
zip_path.parent.mkdir(parents=True, exist_ok=True)
safe_state = _redact(state.to_dict())
meta = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"platform": platform.platform(),
"python": platform.python_version(),
}
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as archive:
archive.writestr("state_redacted.json", json.dumps(safe_state, ensure_ascii=True, indent=2))
archive.writestr("meta.json", json.dumps(meta, ensure_ascii=True, indent=2))
archive.writestr("recent_logs.txt", "\n".join(_redact_log_line(line) for line in logs[-2000:]))
return zip_path