ovdashboard/api/ovdashboard_api/routers/v1/image.py

106 lines
2.3 KiB
Python

"""
Router "image" provides:
- listing image files
- finding image files by name prefix
- getting image files in a uniform format by name prefix
"""
import re
from io import BytesIO
from logging import getLogger
from typing import Iterator
from fastapi import APIRouter, Depends
from fastapi.responses import StreamingResponse
from PIL import Image
from ...config import Config, ImageUIConfig
from ...dav_common import webdav_ensure_path
from ...dav_file import DavFile
from ._common import FileNameLister, PrefixFinder, PrefixUnique
_logger = getLogger(__name__)
router = APIRouter(prefix="/image", tags=["image"])
image_lister = FileNameLister(
path_name="image_dir",
re=re.compile(
r"\.(gif|jpe?g|tiff?|png|bmp)$",
flags=re.IGNORECASE,
),
)
image_finder = PrefixFinder(image_lister)
image_unique = PrefixUnique(image_finder)
@router.on_event("startup")
async def start_router() -> None:
_logger.debug(f"{router.prefix} router starting.")
webdav_ensure_path(await image_lister.remote_path)
@router.get(
"/list",
response_model=list[str],
responses=image_lister.responses,
)
async def list_images(
names: Iterator[str] = Depends(image_lister),
) -> list[str]:
return list(names)
@router.get(
"/find/{prefix}",
response_model=list[str],
responses=image_finder.responses,
)
async def find_images(
names: Iterator[str] = Depends(image_finder),
) -> list[str]:
return list(names)
@router.get(
"/get/{prefix}",
response_class=StreamingResponse,
responses=image_unique.responses,
)
async def get_image(
prefix: str,
name: str = Depends(image_unique),
) -> StreamingResponse:
cfg = await Config.get()
dav_file = DavFile(f"{await image_lister.remote_path}/{name}")
img = Image.open(
BytesIO(await dav_file.as_bytes)
).convert(
cfg.image.mode
)
img_buffer = BytesIO()
img.save(img_buffer, **cfg.image.save_params)
img_buffer.seek(0)
return StreamingResponse(
content=img_buffer,
media_type="image/jpeg",
headers={
"Content-Disposition": f"filename={prefix}.jpg"
},
)
@router.get(
"/config",
response_model=ImageUIConfig,
)
async def get_ui_config(
cfg: Config = Depends(Config.get),
) -> ImageUIConfig:
return cfg.image