"""Source-only rendition for the current 410 × 502 watch display.""" import hashlib import json import logging from datetime import datetime from zoneinfo import ZoneInfo from pigway_frame_flow.errors import FlowError from pigway_frame_flow.renderers.images import convert from pigway_frame_flow.storage.database import encode logger = logging.getLogger(__name__) SIZE = (410, 502) def publish(service, device_id, asset_id, data=None, plan_id=None): # Templates and old gallery assets have no verified undecorated source. row = service.db.one( "SELECT payload FROM asset_sources WHERE asset_id=?", (asset_id,) ) source = json.loads(row["payload"]) if row else {} if source.get("type") != "photo_source": return None try: from pigway_frame_flow.display.thumbnail_plans import get_plan, render plan = get_plan(service, plan_id) if plan_id else None size = (plan.width, plan.height) if plan else SIZE if data is None: data, _, _ = service.photo_sources.read( source["source_id"], source["item_id"], target_size=size ) rendered = ( render(data, plan) if plan else convert(data, "cover", "color", size=SIZE) ) asset = service.assets.put(rendered, "watch.jpg", "cache") now = datetime.now(ZoneInfo(service.settings.timezone)) result = { "asset_id": asset["asset_id"], "url": asset["url"], "width": size[0], "height": size[1], "date": now.date().isoformat(), "timezone": service.settings.timezone, "generated_at": now.isoformat(), "sha256": hashlib.sha256(rendered).hexdigest(), "bytes": len(rendered), "source": source, "fit": plan.fit if plan else "cover", "plan_id": plan_id, "plan": plan.model_dump() if plan else None, "source_rendition": "preview" if service.photo_sources.get(source["source_id"]).kind == "synology-photos" else "source", } from pigway_frame_flow.display.thumbnail_gallery import record record(service, asset["asset_id"], {**result, "source_frame_id": device_id}) service.db.execute( "INSERT OR REPLACE INTO app_config VALUES(?,?)", ("wrist-thumbnail:" + device_id, encode(result)), ) return result except (FlowError, OSError, ValueError): # An auxiliary rendition must never cause a successful upload to replay. logger.warning("Watch thumbnail generation failed for asset %s", asset_id) return None