from __future__ import annotations from dataclasses import dataclass from datetime import datetime from pathlib import Path from typing import Optional @dataclass(frozen=True) class RecordingItem: camera: str filename: str timestamp: str url: str def _parse_filename(filename: str) -> Optional[datetime]: if filename.endswith(".fmp4"): stem = filename[:-5] elif filename.endswith(".mp4"): stem = filename[:-4] else: return None for fmt in ("%Y-%m-%d_%H-%M-%S-%f", "%Y-%m-%d_%H-%M-%S"): try: return datetime.strptime(stem, fmt) except ValueError: continue return None def list_recordings( recordings_dir: str, camera: str, date: Optional[str], limit: int, offset: int, ) -> list[RecordingItem]: base = Path(recordings_dir) cam_dir = base / camera if not cam_dir.exists() or not cam_dir.is_dir(): return [] items: list[tuple[datetime, str, str]] = [] for p in cam_dir.rglob("*"): if not p.is_file(): continue if not (p.name.endswith(".fmp4") or p.name.endswith(".mp4")): continue dt = _parse_filename(p.name) or datetime.fromtimestamp(p.stat().st_mtime) if date is not None and dt.strftime("%Y-%m-%d") != date: continue rel = p.relative_to(base).as_posix() items.append((dt, p.name, rel)) items.sort(key=lambda x: x[0], reverse=True) sliced = items[offset : offset + limit] out: list[RecordingItem] = [] for dt, name, rel in sliced: out.append( RecordingItem( camera=camera, filename=name, timestamp=dt.isoformat(), url=f"/videos/{rel}", ) ) return out