54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
|
|
def disk_usage(path: str) -> dict:
|
|
usage = os.statvfs(path)
|
|
total = usage.f_frsize * usage.f_blocks
|
|
free = usage.f_frsize * usage.f_bavail
|
|
used = total - free
|
|
return {"total": total, "used": used, "free": free}
|
|
|
|
|
|
def drive_stats(config: dict) -> list[dict]:
|
|
stats = []
|
|
for drive in config.get("drives", []):
|
|
path = Path(drive["path"])
|
|
path.mkdir(parents=True, exist_ok=True)
|
|
usage = disk_usage(str(path))
|
|
stats.append({**drive, **usage})
|
|
return stats
|
|
|
|
|
|
def find_existing_home(config: dict, title: str) -> str | None:
|
|
normalized = title.lower()
|
|
for drive in config.get("drives", []):
|
|
root = Path(drive["path"])
|
|
for folder in ("Movies", "Shows"):
|
|
base = root / folder
|
|
if not base.exists():
|
|
continue
|
|
for child in base.iterdir():
|
|
if child.is_dir() and child.name.lower().startswith(normalized):
|
|
return str(root)
|
|
return None
|
|
|
|
|
|
def choose_drive(config: dict, title: str) -> dict:
|
|
existing = find_existing_home(config, title)
|
|
if existing:
|
|
for drive in config.get("drives", []):
|
|
if drive["path"] == existing:
|
|
return drive
|
|
candidates = []
|
|
for drive in drive_stats(config):
|
|
min_free = int(drive.get("min_free_gb", 0)) * 1024**3
|
|
if drive["free"] >= min_free:
|
|
candidates.append(drive)
|
|
if not candidates:
|
|
raise RuntimeError("No media drive has the configured minimum free space")
|
|
return max(candidates, key=lambda d: d["free"])
|
|
|