all
This commit is contained in:
+39
-14
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user