Files
getDomain/domain-api/app/core/files.py
Your Name 0e096947fc debug
2026-04-17 15:13:46 +08:00

179 lines
5.5 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
from datetime import datetime
from app.core.config import settings
def domain_root() -> Path:
return Path(settings.domain_root)
def resolve_domain_path(*relative_paths: str) -> Path | None:
root = domain_root()
candidates: list[Path] = []
seen: set[str] = set()
for relative_path in relative_paths:
text = str(relative_path or "").strip()
if not text:
continue
candidate = root / text
candidate_key = str(candidate)
if candidate_key not in seen:
seen.add(candidate_key)
candidates.append(candidate)
if "/" not in text and "\\" not in text:
nested_candidate = root / "logs" / text
nested_key = str(nested_candidate)
if nested_key not in seen:
seen.add(nested_key)
candidates.append(nested_candidate)
for candidate in candidates:
if candidate.exists():
return candidate
return candidates[0] if candidates else None
def read_json(relative_path: str, default: dict | list | None = None):
path = domain_root() / relative_path
if not path.exists():
return {} if default is None else default
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except (json.JSONDecodeError, OSError):
return {} if default is None else default
def write_json(relative_path: str, payload) -> None:
path = domain_root() / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w", encoding="utf-8") as handle:
json.dump(payload, handle, ensure_ascii=False, indent=2)
def tail_lines(relative_path: str, max_lines: int = 120) -> list[str]:
path = resolve_domain_path(relative_path)
if path is None or not path.exists():
return []
with path.open("r", encoding="utf-8", errors="replace") as handle:
return handle.read().splitlines()[-max_lines:]
def runtime_root() -> Path:
path = Path(__file__).resolve().parents[2] / "runtime"
path.mkdir(parents=True, exist_ok=True)
return path
def read_runtime_json(filename: str, default: dict | list | None = None):
path = runtime_root() / filename
if not path.exists():
return {} if default is None else default
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except (json.JSONDecodeError, OSError):
return {} if default is None else default
def write_runtime_json(filename: str, payload) -> None:
path = runtime_root() / filename
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w", encoding="utf-8") as handle:
json.dump(payload, handle, ensure_ascii=False, indent=2, default=str)
def exports_root() -> Path:
path = runtime_root() / "exports"
path.mkdir(parents=True, exist_ok=True)
return path
def import_root() -> Path:
path = runtime_root() / "imports"
path.mkdir(parents=True, exist_ok=True)
return path
def settings_backup_root() -> Path:
path = runtime_root() / "settings_backups"
path.mkdir(parents=True, exist_ok=True)
return path
def load_export_records() -> list[dict]:
path = runtime_root() / "export_tasks.json"
if not path.exists():
return []
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except (json.JSONDecodeError, OSError):
return []
def save_export_record(record: dict) -> None:
records = load_export_records()
records.insert(0, record)
path = runtime_root() / "export_tasks.json"
with path.open("w", encoding="utf-8") as handle:
json.dump(records[:200], handle, ensure_ascii=False, indent=2, default=str)
def load_import_records() -> list[dict]:
path = runtime_root() / "import_tasks.json"
if not path.exists():
return []
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except (json.JSONDecodeError, OSError):
return []
def save_import_records(records: list[dict]) -> None:
path = runtime_root() / "import_tasks.json"
with path.open("w", encoding="utf-8") as handle:
json.dump(records[:200], handle, ensure_ascii=False, indent=2, default=str)
def load_juming_records() -> list[dict]:
path = runtime_root() / "juming_tasks.json"
if not path.exists():
return []
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except (json.JSONDecodeError, OSError):
return []
def save_juming_records(records: list[dict]) -> None:
path = runtime_root() / "juming_tasks.json"
with path.open("w", encoding="utf-8") as handle:
json.dump(records[:200], handle, ensure_ascii=False, indent=2, default=str)
def load_detect_records() -> list[dict]:
path = runtime_root() / "detect_runs.json"
if not path.exists():
return []
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except (json.JSONDecodeError, OSError):
return []
def save_detect_records(records: list[dict]) -> None:
path = runtime_root() / "detect_runs.json"
with path.open("w", encoding="utf-8") as handle:
json.dump(records[:200], handle, ensure_ascii=False, indent=2, default=str)
def timestamp_filename(prefix: str, ext: str) -> str:
return f"{prefix}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.{ext}"