Init photobooth - borne photo evenementielle RPi4
Backend FastAPI complet : camera gphoto2, filtres/overlays Pillow, chroma key OpenCV, multi-shot/collage, GIF, impression CUPS, email SMTP, QR code. Frontend web vanilla (HTML/CSS/JS) pour Chromium kiosk. Menu admin cache (appui long coin ecran). Toutes les fonctionnalites activables/desactivables. Scripts install + systemd pour RPi4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
59
backend/gallery.py
Normal file
59
backend/gallery.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from backend.config import DOSSIER_PHOTOS, DOSSIER_EXPORTS
|
||||
|
||||
log = logging.getLogger("photobooth.gallery")
|
||||
|
||||
|
||||
def lister_photos(dossier: str = "exports") -> list[dict]:
|
||||
"""Liste les photos d'un dossier avec leurs metadonnees."""
|
||||
chemin = DOSSIER_EXPORTS if dossier == "exports" else DOSSIER_PHOTOS
|
||||
photos = []
|
||||
extensions = {".jpg", ".jpeg", ".png", ".gif"}
|
||||
|
||||
if not chemin.exists():
|
||||
return photos
|
||||
|
||||
for fichier in sorted(chemin.iterdir(), key=lambda f: f.stat().st_mtime, reverse=True):
|
||||
if fichier.suffix.lower() in extensions:
|
||||
stat = fichier.stat()
|
||||
photos.append({
|
||||
"nom": fichier.name,
|
||||
"chemin": str(fichier.relative_to(chemin.parent.parent)),
|
||||
"taille": stat.st_size,
|
||||
"date": datetime.fromtimestamp(stat.st_mtime).isoformat(),
|
||||
})
|
||||
return photos
|
||||
|
||||
|
||||
def compter_photos() -> dict:
|
||||
"""Retourne le compteur de photos pour l'evenement."""
|
||||
nb_photos = len(list(DOSSIER_PHOTOS.glob("*.jpg"))) + len(list(DOSSIER_PHOTOS.glob("*.jpeg")))
|
||||
nb_exports = len(list(DOSSIER_EXPORTS.glob("*"))) - len(list(DOSSIER_EXPORTS.glob(".gitkeep")))
|
||||
return {
|
||||
"photos_prises": nb_photos,
|
||||
"exports": max(0, nb_exports),
|
||||
}
|
||||
|
||||
|
||||
def supprimer_photo(nom: str, dossier: str = "exports") -> bool:
|
||||
"""Supprime une photo par son nom."""
|
||||
chemin = DOSSIER_EXPORTS if dossier == "exports" else DOSSIER_PHOTOS
|
||||
fichier = chemin / nom
|
||||
if fichier.exists() and fichier.parent == chemin:
|
||||
fichier.unlink()
|
||||
log.info(f"Photo supprimee : {fichier}")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def vider_galerie():
|
||||
"""Supprime toutes les photos (reset evenement)."""
|
||||
for dossier in [DOSSIER_PHOTOS, DOSSIER_EXPORTS]:
|
||||
for fichier in dossier.iterdir():
|
||||
if fichier.name != ".gitkeep":
|
||||
fichier.unlink()
|
||||
log.info("Galerie videe")
|
||||
Reference in New Issue
Block a user