Add read-only Synology Photos people filtering
This commit is contained in:
@@ -18,6 +18,7 @@ from pigway_frame_flow.errors import ErrorCode as E
|
||||
from pigway_frame_flow.errors import FlowError
|
||||
from pigway_frame_flow.models import StrictModel
|
||||
from pigway_frame_flow.providers.photo_names import path_caption
|
||||
from pigway_frame_flow.providers.synology_photos import SynologyPhotos
|
||||
from pigway_frame_flow.settings import secret
|
||||
from pigway_frame_flow.storage.database import encode
|
||||
|
||||
@@ -32,6 +33,9 @@ class PhotoSourceInput(StrictModel):
|
||||
synology_previews: bool = False
|
||||
organized_only: bool = False
|
||||
folder_caption: bool = False
|
||||
people_filter: bool = False
|
||||
person_ids: list[int] = Field(default_factory=list, max_length=50)
|
||||
person_match: Literal["any", "all"] = "any"
|
||||
credential_env: str | None = Field(
|
||||
default=None, pattern=r"^FRAME_FLOW_SOURCE_[A-Z0-9_]+$"
|
||||
)
|
||||
@@ -62,6 +66,7 @@ class PhotoSources:
|
||||
def __init__(self, db, settings, assets):
|
||||
self.db, self.settings, self.assets = db, settings, assets
|
||||
self.cache = {}
|
||||
self.synology = SynologyPhotos(settings)
|
||||
# Register provider secrets before request IDs or errors can be reflected.
|
||||
for row in self.list():
|
||||
if row["kind"] == "webdav" and row.get("credential_env"):
|
||||
@@ -91,6 +96,19 @@ class PhotoSources:
|
||||
return PhotoSourceInput.model_validate_json(row["payload"])
|
||||
|
||||
def save(self, source_id, source):
|
||||
if source.people_filter and source.kind != "local":
|
||||
raise FlowError(
|
||||
E.INVALID_REQUEST,
|
||||
"Person filtering requires a local Synology photo source",
|
||||
)
|
||||
if any(i <= 0 for i in source.person_ids) or len(set(source.person_ids)) != len(
|
||||
source.person_ids
|
||||
):
|
||||
raise FlowError(
|
||||
E.INVALID_REQUEST, "Person IDs must be unique positive integers"
|
||||
)
|
||||
if source.people_filter and not source.person_ids:
|
||||
raise FlowError(E.INVALID_REQUEST, "Select at least one person")
|
||||
if source.kind == "local":
|
||||
self.local_directory(source.location)
|
||||
if source.credential_env:
|
||||
@@ -226,6 +244,11 @@ class PhotoSources:
|
||||
cached = self.cache.get(source_id)
|
||||
if cached and not refresh and time.monotonic() - cached[0] < 60:
|
||||
return cached[1]
|
||||
allowed = (
|
||||
self.synology.paths(source.person_ids, source.person_match, refresh=refresh)
|
||||
if source.people_filter
|
||||
else None
|
||||
)
|
||||
items = []
|
||||
if source.kind == "local":
|
||||
directory = self.local_directory(source.location)
|
||||
@@ -267,6 +290,8 @@ class PhotoSources:
|
||||
if large and not preview:
|
||||
continue
|
||||
relative = path.relative_to(root).as_posix()
|
||||
if allowed is not None and relative not in allowed:
|
||||
continue
|
||||
items.append(
|
||||
{
|
||||
"id": relative,
|
||||
|
||||
Reference in New Issue
Block a user