Add Plex-ready race + season poster endpoints
GET /posters/race/{grand_prix_name}/{season}.png
GET /posters/season/{season}.png
1000x1500 PNGs composed with Pillow + cairosvg:
checkered-flag strips top/bottom, F1 wordmark, round/year ribbon,
GP name, rasterised track outline (white), race date. Season poster
is wordmark + giant year + 'WORLD CHAMPIONSHIP'. Cached under
cache/posters/ so cold renders happen once.
This commit is contained in:
+32
-2
@@ -1,11 +1,13 @@
|
||||
from fastapi import FastAPI, HTTPException, Response
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.responses import FileResponse, Response as FastAPIResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pathlib import Path
|
||||
import logging
|
||||
|
||||
# Import our CircuitService
|
||||
from circuits_service import CircuitService, Format
|
||||
from ergast_service import ErgastService
|
||||
from posters_service import PostersService
|
||||
from models.track_layout import TrackLayout
|
||||
|
||||
# Initialize FastAPI app
|
||||
@@ -30,6 +32,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Initialize CircuitService
|
||||
circuit_service = CircuitService()
|
||||
ergast_service = ErgastService(circuit_service)
|
||||
posters_service = PostersService(circuit_service, ergast_service)
|
||||
|
||||
def get_content_disposition(format: Format) -> str:
|
||||
if format == Format.PNG:
|
||||
@@ -59,10 +63,36 @@ async def root():
|
||||
"/circuits/{country_slug}/{city_slug}/{circuit_slug}/layout/{layout_slug}",
|
||||
"/tracks/{country_slug}/{city_slug}/{circuit_slug}/year/{year}/{format}",
|
||||
"/tracks/{country_slug}/{city_slug}/{circuit_slug}/layout/{layout_slug}/{format}",
|
||||
"/grand-prix/{grand_prix_name}/year/{year}"
|
||||
"/grand-prix/{grand_prix_name}/year/{year}",
|
||||
"/posters/race/{grand_prix_name}/{season}.png",
|
||||
"/posters/season/{season}.png",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@app.get("/posters/race/{grand_prix_name}/{season}.png")
|
||||
async def get_race_poster(grand_prix_name: str, season: int):
|
||||
"""Plex-ready 1000x1500 race poster (PNG). Cached on disk."""
|
||||
png = posters_service.render_race_poster(grand_prix_name, season)
|
||||
if not png:
|
||||
raise HTTPException(status_code=404, detail=f"No poster available for {grand_prix_name} {season}")
|
||||
return FastAPIResponse(
|
||||
content=png,
|
||||
media_type="image/png",
|
||||
headers={"Cache-Control": "public, max-age=31536000"},
|
||||
)
|
||||
|
||||
|
||||
@app.get("/posters/season/{season}.png")
|
||||
async def get_season_poster(season: int):
|
||||
"""Plex-ready 1000x1500 season poster (PNG). Cached on disk."""
|
||||
png = posters_service.render_season_poster(season)
|
||||
return FastAPIResponse(
|
||||
content=png,
|
||||
media_type="image/png",
|
||||
headers={"Cache-Control": "public, max-age=31536000"},
|
||||
)
|
||||
|
||||
@app.get("/circuits")
|
||||
async def get_countries():
|
||||
"""Get list of all available countries with their slugs"""
|
||||
|
||||
Reference in New Issue
Block a user