Add starred cloud photos and opt-in seven-day random upload retention
This commit is contained in:
@@ -161,3 +161,25 @@ Random rendering tries at most five distinct candidates before any device write,
|
||||
skipping only invalid or unavailable images. Explicit selections never fall back.
|
||||
Operation `result.photo_attempts` records source-relative item IDs, names, status
|
||||
and stable error codes, including failures. This does not retry upload or switch.
|
||||
|
||||
### Starred cloud photos and seven-day retention
|
||||
|
||||
Automation `cleanup_unstarred` is opt-in and defaults to false. It is valid only
|
||||
for random photo-source jobs. New uploads retain their confirmed cloud image ID
|
||||
and an expiry seven days after upload. Existing images are never backfilled.
|
||||
The cloud gallery's star button stores a Frame Flow star in SQLite; it does not
|
||||
modify Synology Photos favorites or synchronize with KoKonna app favorites.
|
||||
Starred images stay; unstarred overdue images are eligible for deletion from the
|
||||
KoKonna cloud gallery. NAS originals and local Frame Flow assets remain.
|
||||
|
||||
The scheduler checks hourly, queues at most 20 deletions per cycle, and rechecks
|
||||
stars and protection when executing. Current, previous/restore, override,
|
||||
playlist and explicit job image references are protected. Offline devices and
|
||||
write-disabled services skip cleanup. A failed or unknown deletion is retained
|
||||
for investigation and is not retried automatically. Unstarring an expired image
|
||||
makes it eligible at the next check. Removing a job does not cancel retention
|
||||
already assigned to its uploads; star these images to keep them.
|
||||
|
||||
API: `PUT /api/v1/devices/{device_id}/images/{image_id}/star` with
|
||||
`{"starred": true}`; scope `images:write`. Gallery responses add `starred` and
|
||||
`expires_at`. All cleanup uses the existing operation queue, history and driver.
|
||||
|
||||
@@ -1400,6 +1400,173 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/devices/{device_id}/images/{image_id}/star": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"Images"
|
||||
],
|
||||
"summary": "Star Image",
|
||||
"operationId": "star_image_api_v1_devices__device_id__images__image_id__star_put",
|
||||
"security": [
|
||||
{
|
||||
"HTTPBearer": []
|
||||
},
|
||||
{
|
||||
"AccountSession": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "device_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Device Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "image_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"title": "Image Id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ImageStar"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Bad Request"
|
||||
},
|
||||
"401": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Unauthorized"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Not Found"
|
||||
},
|
||||
"409": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Conflict"
|
||||
},
|
||||
"413": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Content Too Large"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Unprocessable Content"
|
||||
},
|
||||
"429": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Too Many Requests"
|
||||
},
|
||||
"500": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Internal Server Error"
|
||||
},
|
||||
"502": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Bad Gateway"
|
||||
},
|
||||
"503": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Service Unavailable"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/devices/{device_id}/images/{image_id}/file": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -10094,6 +10261,22 @@
|
||||
},
|
||||
"GalleryImage": {
|
||||
"properties": {
|
||||
"starred": {
|
||||
"type": "boolean",
|
||||
"title": "Starred",
|
||||
"default": false
|
||||
},
|
||||
"expires_at": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Expires At"
|
||||
},
|
||||
"width": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -10328,6 +10511,20 @@
|
||||
],
|
||||
"title": "ImageContent"
|
||||
},
|
||||
"ImageStar": {
|
||||
"properties": {
|
||||
"starred": {
|
||||
"type": "boolean",
|
||||
"title": "Starred"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"starred"
|
||||
],
|
||||
"title": "ImageStar"
|
||||
},
|
||||
"ImageURLConfig": {
|
||||
"properties": {
|
||||
"allowed_hosts": {
|
||||
@@ -10345,6 +10542,11 @@
|
||||
},
|
||||
"Job": {
|
||||
"properties": {
|
||||
"cleanup_unstarred": {
|
||||
"type": "boolean",
|
||||
"title": "Cleanup Unstarred",
|
||||
"default": false
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"title": "Enabled",
|
||||
@@ -10481,6 +10683,11 @@
|
||||
},
|
||||
"JobInput": {
|
||||
"properties": {
|
||||
"cleanup_unstarred": {
|
||||
"type": "boolean",
|
||||
"title": "Cleanup Unstarred",
|
||||
"default": false
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"title": "Enabled",
|
||||
@@ -10812,6 +11019,11 @@
|
||||
},
|
||||
"Options": {
|
||||
"properties": {
|
||||
"cleanup_unstarred": {
|
||||
"type": "boolean",
|
||||
"title": "Cleanup Unstarred",
|
||||
"default": false
|
||||
},
|
||||
"duration": {
|
||||
"type": "integer",
|
||||
"maximum": 604800.0,
|
||||
|
||||
Reference in New Issue
Block a user