diff --git a/api/advent22_api/dav_common.py b/api/advent22_api/dav_common.py index 9a83a1b..30714e5 100644 --- a/api/advent22_api/dav_common.py +++ b/api/advent22_api/dav_common.py @@ -24,6 +24,11 @@ async def dav_list_files(regex: re.Pattern, directory: str = "") -> list[str]: ] +@AsyncTTL(time_to_live=SETTINGS.cache_ttl) +async def dav_file_exists(path: str) -> bool: + return _WEBDAV_CLIENT.check(path) + + @AsyncTTL(time_to_live=SETTINGS.cache_ttl) async def dav_get_file(path: str) -> BytesIO: resource = _WEBDAV_CLIENT.resource(path) diff --git a/api/advent22_api/routers/days.py b/api/advent22_api/routers/days.py index c8e403f..e1dd90d 100644 --- a/api/advent22_api/routers/days.py +++ b/api/advent22_api/routers/days.py @@ -7,7 +7,7 @@ from fastapi.responses import StreamingResponse from PIL import ImageFont from ..config import Config, get_config -from ..dav_common import dav_get_file, dav_list_files +from ..dav_common import dav_file_exists, dav_get_file, dav_list_files from ._image import AdventImage from ._misc import get_rnd, set_length, shuffle @@ -60,53 +60,74 @@ _RE_IMAGE_FILE = re.compile( ) -async def get_images() -> list[str]: - ls = await dav_list_files(_RE_IMAGE_FILE, "/images") +async def list_images_auto() -> list[str]: + ls = await dav_list_files(_RE_IMAGE_FILE, "/images_auto") ls = await set_length(ls, 24) return await shuffle(ls) async def load_image( - index: int, - images: list[str] = Depends(get_images), -) -> AdventImage: + file_name: str, +) -> AdventImage | None: """ - Bild laden und einen quadratischen Ausschnitt - aus der Mitte nehmen + Versuche, Bild aus Datei zu laden """ - # Bild laden - img_buffer = await dav_get_file(images[index]) + if not await dav_file_exists(file_name): + return None + + img_buffer = await dav_get_file(file_name) img_buffer.seek(0) return await AdventImage.load_standard(img_buffer) +async def get_auto_image( + index: int, + letter: str = Depends(get_letter), + images: list[str] = Depends(list_images_auto), +) -> AdventImage: + + image = await load_image(images[index]) + assert image is not None + + rnd = await get_rnd(index) + + # Buchstabe verstecken + await image.hide_text( + xy=tuple(rnd.choices(range(30, 470), k=2)), + text=letter, + font=ImageFont.truetype("Lena.ttf", 50), + ) + + return image + + @router.get( "/picture/{index}", response_class=StreamingResponse, ) async def get_picture_for_day( index: int, - letter: str = Depends(get_letter), - adv_img: AdventImage = Depends(load_image), ) -> StreamingResponse: """ Bild für einen Tag erstellen """ - rnd = await get_rnd(index) + # Versuche, aus "manual"-Ordner zu laden + image = await load_image(f"images_manual/{index}.jpg") - # Buchstabe verstecken - await adv_img.hide_text( - xy=tuple(rnd.choices(range(30, 470), k=2)), - text=letter, - font=ImageFont.truetype("Lena.ttf", 50), - ) + if image is None: + # Erstelle automatisch generiertes Bild + image = await get_auto_image( + index=index, + letter=await get_letter(index, await get_config()), + images=await list_images_auto() + ) # Bilddaten in Puffer laden img_buffer = BytesIO() - adv_img.img.save(img_buffer, format="JPEG", quality=85) + image.img.save(img_buffer, format="JPEG", quality=85) img_buffer.seek(0) return StreamingResponse(