Add read-only NAS and WebDAV photo sources with random scheduling

This commit is contained in:
Pigway
2026-10-05 00:52:39 +08:00
parent b530e32c65
commit f5ab1ade77
18 changed files with 5578 additions and 84 deletions
+58 -1
View File
@@ -42,6 +42,7 @@ from pigway_frame_flow.models import (
JobInput,
Operation,
Options,
PhotoSourceContent,
Playlist,
PlaylistInput,
Profile,
@@ -57,6 +58,11 @@ from pigway_frame_flow.models import (
WeatherConfig,
WeatherView,
)
from pigway_frame_flow.providers.photo_sources import (
PhotoCatalog,
PhotoSourceInput,
PhotoSourceView,
)
from pigway_frame_flow.providers.weather import ConfigurableWeatherProvider
from pigway_frame_flow.renderers.images import Assets, convert
from pigway_frame_flow.renderers.templates import TemplateRenderer
@@ -426,7 +432,7 @@ def create_app(settings=None, start_worker=True):
)
def upload(
device_id: str,
payload: ImageContent | URLContent,
payload: ImageContent | URLContent | PhotoSourceContent,
request: Request,
display_now: bool = False,
idempotency_key: str | None = Header(default=None),
@@ -537,6 +543,57 @@ def create_app(settings=None, start_worker=True):
def asset_file(asset_id: str):
return FileResponse(assets.path(asset_id), media_type="image/jpeg")
@app.get(
"/api/v1/photo-sources",
response_model=list[PhotoSourceView],
tags=["Photo sources"],
dependencies=[Depends(require("images:read"))],
)
def photo_sources():
return service.photo_sources.list()
@app.put(
"/api/v1/photo-sources/{source_id}",
response_model=PhotoSourceView,
tags=["Photo sources"],
dependencies=[Depends(require("admin"))],
)
def save_photo_source(source_id: str, payload: PhotoSourceInput):
if not re.fullmatch(r"[a-z0-9-]{1,60}", source_id):
raise FlowError(E.INVALID_REQUEST, "Invalid source ID")
return service.photo_sources.save(source_id, payload)
@app.delete(
"/api/v1/photo-sources/{source_id}",
status_code=204,
tags=["Photo sources"],
dependencies=[Depends(require("admin"))],
)
def delete_photo_source(source_id: str):
service.photo_sources.delete(source_id)
return Response(status_code=204)
@app.get(
"/api/v1/photo-sources/{source_id}/images",
response_model=PhotoCatalog,
tags=["Photo sources"],
dependencies=[Depends(require("images:read"))],
)
def source_images(
source_id: str,
offset: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=200),
refresh: bool = False,
):
items = service.photo_sources.catalog(source_id, refresh=refresh)
return {
"items": items[offset : offset + limit],
"total": len(items),
"offset": offset,
"limit": limit,
"catalog_limit": 10000,
}
@app.delete(
"/api/v1/devices/{device_id}/images/{image_id}",
response_model=Accepted,