zapret-kvn/xray_fluent/diagnostics.py
loop-uh a7cf61a05e
All checks were successful
Windows project source guards / test (push) Successful in 36s
Prepare v0.4.79: unified theming, responsive layout, real flags
- Single source of truth for theme: theme.py tokens, FluentDialog base
  for all dialogs, setCustomStyleSheet migration, theme applied before
  window creation, SystemThemeListener for auto mode
- Responsive layout: ScrollablePage base with as-needed horizontal
  scrolling, word wrap on dashboard labels, adaptive dashboard grid,
  realistic 860x560 window minimum
- Real country flags (flagcdn PNG set) with themed border and fallback
- Active server row marked by accent stripe only (no synthesized bold)
- Subscription polish from parallel work (QR utils, http, diagnostics)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 23:21:28 +03:00

76 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",
"hwid",
"subscription_device_id",
}
_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