all
🚀 Deploy — JH Photomaton / 🔍 Vérification (push) Has been cancelled
🚀 Deploy — JH Photomaton / 🍓 Deploy sur le Pi (push) Has been cancelled

This commit is contained in:
2026-07-17 00:44:22 +02:00
parent 209f81aa3d
commit 9a006f1457
23 changed files with 3712 additions and 484 deletions
+39 -14
View File
@@ -1,12 +1,15 @@
"""Galerie publique accessible sans authentification."""
"""Galerie publique -- accessible sans authentification."""
import asyncio
import logging
from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from datetime import datetime
from pathlib import Path
import httpx
from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse, RedirectResponse, Response
from fastapi.templating import Jinja2Templates
logger = logging.getLogger(__name__)
router = APIRouter()
@@ -15,7 +18,6 @@ _templates = Jinja2Templates(directory=Path(__file__).parent.parent.parent / "fr
@router.get("/", response_class=HTMLResponse)
async def index(request: Request):
"""Page d'accueil → redirige vers la galerie publique."""
return RedirectResponse(url="/gallery")
@@ -23,7 +25,7 @@ async def index(request: Request):
async def gallery_page(request: Request):
cfg = request.app.state.config
if not cfg.gallery.public_enabled:
return HTMLResponse("<h1>Galerie désactivée</h1>", status_code=403)
return HTMLResponse("<h1>Galerie desactivee</h1>", status_code=403)
return _templates.TemplateResponse("public/gallery.html", {"request": request, "config": cfg})
@@ -33,13 +35,9 @@ async def api_gallery_photos(
page: int = Query(default=1, ge=1),
limit: int = Query(default=24, ge=1, le=100),
):
"""Liste des photos depuis photobooth-app (paginée)."""
pb = request.app.state.photobooth_service
cfg = request.app.state.config
all_photos = await pb.get_media_collection(limit=500)
# Filtre sur les images uniquement
photos = [p for p in all_photos if _is_image(p)]
total = len(photos)
@@ -47,7 +45,6 @@ async def api_gallery_photos(
end = start + limit
page_photos = photos[start:end]
# Enrichit avec les URLs
for p in page_photos:
pid = _get_id(p)
p["full_url"] = pb.media_url(pid)
@@ -64,9 +61,37 @@ async def api_gallery_photos(
@router.get("/api/gallery/download/{photo_id}")
async def download_photo(request: Request, photo_id: str):
"""Redirige vers le fichier full-res sur photobooth-app."""
"""Proxy la photo full-res avec un nom de fichier lie a l'evenement en cours."""
pb = request.app.state.photobooth_service
return RedirectResponse(url=pb.media_url(photo_id))
cfg = request.app.state.config
event_svc = getattr(request.app.state, "event_service", None)
img_url = pb.media_url(photo_id)
slug = cfg.event.slug or "photomaton"
date_str = datetime.now().strftime("%Y-%m-%d")
filename = f"{slug}_By_LSDW_{date_str}.jpg"
try:
async with httpx.AsyncClient(timeout=30.0) as client:
r = await client.get(img_url)
r.raise_for_status()
if event_svc:
asyncio.create_task(event_svc.increment(slug, "downloads"))
content_type = r.headers.get("content-type", "image/jpeg")
return Response(
content=r.content,
media_type=content_type,
headers={
"Content-Disposition": f'attachment; filename="{filename}"',
"Content-Length": str(len(r.content)),
"Cache-Control": "no-cache",
},
)
except Exception as e:
logger.warning("Download proxy echoue (%s), fallback redirect: %s", photo_id, e)
return RedirectResponse(url=img_url)
def _is_image(item: dict) -> bool: