Add optional photo providers, layout studio and scoped integrations
This commit is contained in:
@@ -27,7 +27,7 @@ from pigway_frame_flow.storage.database import encode
|
||||
|
||||
class PhotoSourceInput(StrictModel):
|
||||
name: str = Field(min_length=1, max_length=120)
|
||||
kind: Literal["local", "webdav"]
|
||||
kind: Literal["local", "webdav", "google-drive", "alipan", "baidu"]
|
||||
location: str = Field(min_length=1, max_length=2048)
|
||||
recursive: bool = True
|
||||
enabled: bool = True
|
||||
@@ -36,6 +36,11 @@ class PhotoSourceInput(StrictModel):
|
||||
organized_only: bool = False
|
||||
folder_caption: bool = False
|
||||
orientation: Literal["auto", "landscape", "portrait"] | None = None
|
||||
minimum_sharpness: float = Field(default=0, ge=0, le=10000)
|
||||
minimum_brightness: float = Field(default=0, ge=0, le=255)
|
||||
maximum_brightness: float = Field(default=255, ge=0, le=255)
|
||||
avoid_duplicates: bool = False
|
||||
people_space: Literal["shared", "personal"] = "shared"
|
||||
people_filter: bool = False
|
||||
person_ids: list[int] = Field(default_factory=list, max_length=50)
|
||||
person_match: Literal["any", "all"] = "any"
|
||||
@@ -102,6 +107,15 @@ class PhotoSources:
|
||||
return PhotoSourceInput.model_validate_json(row["payload"])
|
||||
|
||||
def save(self, source_id, source):
|
||||
if source.minimum_brightness > source.maximum_brightness:
|
||||
raise FlowError(E.INVALID_REQUEST, "Brightness range is reversed")
|
||||
if source.kind != "local" and (
|
||||
source.organized_only or source.folder_caption or source.synology_previews
|
||||
):
|
||||
raise FlowError(
|
||||
E.UNSUPPORTED_CAPABILITY,
|
||||
"Folder captions and Synology previews require a local photo source",
|
||||
)
|
||||
if source.orientation and source.kind != "local":
|
||||
raise FlowError(
|
||||
E.UNSUPPORTED_CAPABILITY,
|
||||
@@ -126,7 +140,7 @@ class PhotoSources:
|
||||
raise FlowError(
|
||||
E.INVALID_REQUEST, "Local sources do not use credentials"
|
||||
)
|
||||
else:
|
||||
elif source.kind == "webdav":
|
||||
source = source.model_copy(
|
||||
update={
|
||||
"recursive": False,
|
||||
@@ -266,7 +280,12 @@ class PhotoSources:
|
||||
):
|
||||
return cached[1]
|
||||
allowed = (
|
||||
self.synology.paths(source.person_ids, source.person_match, refresh=refresh)
|
||||
self.synology.paths(
|
||||
source.person_ids,
|
||||
source.person_match,
|
||||
refresh=refresh,
|
||||
space=source.people_space,
|
||||
)
|
||||
if source.people_filter
|
||||
else None
|
||||
)
|
||||
@@ -387,6 +406,10 @@ class PhotoSources:
|
||||
break
|
||||
if len(items) >= source.catalog_limit:
|
||||
break
|
||||
elif source.kind in ("google-drive", "alipan", "baidu"):
|
||||
from pigway_frame_flow.providers.cloud_drives import CloudDrives
|
||||
|
||||
items = CloudDrives(self).catalog(source_id, source)
|
||||
else:
|
||||
data = self.assets.fetch_url(
|
||||
source.location,
|
||||
@@ -503,6 +526,10 @@ class PhotoSources:
|
||||
os.close(parent_fd)
|
||||
except OSError:
|
||||
raise FlowError(E.NOT_FOUND, "Photo is unavailable", 404) from None
|
||||
elif source.kind in ("google-drive", "alipan", "baidu"):
|
||||
from pigway_frame_flow.providers.cloud_drives import CloudDrives
|
||||
|
||||
data = CloudDrives(self).read(source_id, source, item)
|
||||
else:
|
||||
data = self.assets.fetch_url(item["id"], headers=self.headers(source))
|
||||
if len(data) > self.settings.max_bytes:
|
||||
|
||||
Reference in New Issue
Block a user