"""Regenerable BLE library previews, isolated from user-owned media.""" from __future__ import annotations import hashlib import re from io import BytesIO from pathlib import Path from PIL import Image from app.persistence import atomic_write_bytes _PREVIEW_FILE = re.compile(r"[0-9a-f]{64}\.png\Z") class PreviewCache: def __init__(self, data_dir: Path): self.root = Path(data_dir) / "mobile" / "previews" self.root.mkdir(parents=True, exist_ok=True) @staticmethod def name(item: dict) -> str: identity = "\0".join(str(item[key]) for key in ("type", "id", "revision")) return hashlib.sha256(identity.encode("utf-8")).hexdigest() + ".png" def reconcile(self, items: list[dict]) -> None: expected = {self.name(item) for item in items} for path in self.root.iterdir(): if path.is_file() and _PREVIEW_FILE.fullmatch(path.name) and path.name not in expected: path.unlink(missing_ok=True) def get(self, item: dict, image: Image.Image) -> bytes: path = self.root / self.name(item) if path.exists(): try: data = path.read_bytes() with Image.open(BytesIO(data)) as cached: cached.verify() if cached.format == "PNG" and cached.size == (16, 16): return data except (OSError, ValueError): pass output = BytesIO() image.convert("RGB").resize((16, 16), Image.Resampling.LANCZOS).save(output, format="PNG", optimize=True) data = output.getvalue() atomic_write_bytes(path, data) return data