79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
"""Persistent selection preferences scoped to a library and its stable item ID."""
|
|
|
|
from pigway_frame_flow.errors import ErrorCode as E
|
|
from pigway_frame_flow.errors import FlowError
|
|
|
|
|
|
def ensure_compatible(starred, excluded):
|
|
if starred and excluded:
|
|
raise FlowError(
|
|
E.CONFLICT,
|
|
"Starred photos cannot be excluded; clear the existing mark first",
|
|
409,
|
|
)
|
|
|
|
|
|
def flags(db, source_id, item_id):
|
|
row = db.one(
|
|
"SELECT starred,excluded FROM photo_preferences WHERE source_id=? AND item_id=?",
|
|
(source_id, item_id),
|
|
)
|
|
return {key: bool(row and row[key]) for key in ("starred", "excluded")}
|
|
|
|
|
|
def set_flags(db, source_id, item_id, *, starred=None, excluded=None):
|
|
with db.transaction() as connection:
|
|
current = flags(db, source_id, item_id)
|
|
if source_id == "@assets":
|
|
meta = db.one(
|
|
"SELECT starred FROM asset_metadata WHERE asset_id=?", (item_id,)
|
|
)
|
|
current["starred"] = bool(meta and meta["starred"])
|
|
ensure_compatible(
|
|
current["starred"] if starred is None else starred,
|
|
current["excluded"] if excluded is None else excluded,
|
|
)
|
|
connection.execute(
|
|
"INSERT INTO photo_preferences(source_id,item_id,starred,excluded) VALUES(?,?,?,?) ON CONFLICT(source_id,item_id) DO UPDATE SET starred=coalesce(?,starred),excluded=coalesce(?,excluded)",
|
|
(
|
|
source_id,
|
|
item_id,
|
|
int(starred or False),
|
|
int(excluded or False),
|
|
None if starred is None else int(starred),
|
|
None if excluded is None else int(excluded),
|
|
),
|
|
)
|
|
return flags(db, source_id, item_id)
|
|
|
|
|
|
def annotate(db, source_id, items):
|
|
preferences = {
|
|
row["item_id"]: row
|
|
for row in db.all(
|
|
"SELECT item_id,starred,excluded FROM photo_preferences WHERE source_id=?",
|
|
(source_id,),
|
|
)
|
|
}
|
|
return [
|
|
{
|
|
**item,
|
|
**{
|
|
key: bool(preferences.get(item["id"], {}).get(key))
|
|
for key in ("starred", "excluded")
|
|
},
|
|
}
|
|
for item in items
|
|
]
|
|
|
|
|
|
def eligible(db, source_id, items):
|
|
excluded = {
|
|
row["item_id"]
|
|
for row in db.all(
|
|
"SELECT item_id FROM photo_preferences WHERE source_id=? AND excluded=1",
|
|
(source_id,),
|
|
)
|
|
}
|
|
return [item for item in items if item["id"] not in excluded]
|