| """ |
| File Utilities -- AI Reel Creator Platform |
| ========================================= |
| |
| Canonical storage paths, file validation, hash computation. |
| """ |
|
|
| import os |
| import shutil |
| import hashlib |
| from datetime import datetime |
| from pathlib import Path |
| from typing import Optional |
|
|
|
|
| def canonical_storage_path(asset_type: str, source: Optional[str] = "upload", |
| original_filename: Optional[str] = None, |
| base_dir: str = "/data/assets") -> str: |
| """Generate a canonical filesystem path for a stored asset. |
| |
| Pattern: {base_dir}/{YYYY-MM-DD}/{asset_type}/{source}/{uuid}.{ext} |
| """ |
| date_dir = datetime.utcnow().strftime("%Y-%m-%d") |
| ext = Path(original_filename).suffix if original_filename else "" |
| uid = hashlib.sha256(os.urandom(32)).hexdigest()[:16] |
| filename = f"{uid}{ext}" |
| full = Path(base_dir) / date_dir / asset_type / (source or "upload") / filename |
| full.parent.mkdir(parents=True, exist_ok=True) |
| return str(full) |
|
|
|
|
| def compute_file_hash(path: str, algorithm: str = "sha256") -> str: |
| h = hashlib.new(algorithm) |
| with open(path, "rb") as f: |
| for chunk in iter(lambda: f.read(8192), b""): |
| h.update(chunk) |
| return h.hexdigest() |
|
|
|
|
| def validate_file_type(path: str, allowed_extensions: set) -> bool: |
| ext = Path(path).suffix.lower().lstrip(".") |
| return ext in allowed_extensions |
|
|
|
|
| def ensure_dir(path: str) -> Path: |
| p = Path(path) |
| p.mkdir(parents=True, exist_ok=True) |
| return p |
|
|
|
|
| def safe_move(src: str, dst: str) -> str: |
| ensure_dir(Path(dst).parent) |
| shutil.move(src, dst) |
| return dst |
|
|