feat: add matrix staged attachment state

This commit is contained in:
Mikhail Putilovskij 2026-04-20 16:21:00 +03:00
parent 105ecc68ed
commit 0eaf124e21
2 changed files with 188 additions and 0 deletions

View file

@ -1,5 +1,8 @@
from __future__ import annotations
import asyncio
from weakref import WeakValueDictionary
from core.store import StateStore
ROOM_META_PREFIX = "matrix_room:"
@ -9,6 +12,8 @@ SKILLS_MSG_PREFIX = "matrix_skills_msg:"
PENDING_CONFIRM_PREFIX = "matrix_pending_confirm:"
LOAD_PENDING_PREFIX = "matrix_load_pending:"
RESET_PENDING_PREFIX = "matrix_reset_pending:"
STAGED_ATTACHMENTS_PREFIX = "matrix_staged_attachments:"
_STAGED_ATTACHMENTS_LOCKS: WeakValueDictionary[str, asyncio.Lock] = WeakValueDictionary()
async def get_room_meta(store: StateStore, room_id: str) -> dict | None:
@ -126,3 +131,66 @@ async def set_reset_pending(
async def clear_reset_pending(store: StateStore, user_id: str, room_id: str) -> None:
await store.delete(_reset_pending_key(user_id, room_id))
def _staged_attachments_key(room_id: str, user_id: str) -> str:
return f"{STAGED_ATTACHMENTS_PREFIX}{room_id}:{user_id}"
def _staged_attachments_lock(room_id: str, user_id: str) -> asyncio.Lock:
key = _staged_attachments_key(room_id, user_id)
lock = _STAGED_ATTACHMENTS_LOCKS.get(key)
if lock is None:
lock = asyncio.Lock()
_STAGED_ATTACHMENTS_LOCKS[key] = lock
return lock
async def get_staged_attachments(
store: StateStore, room_id: str, user_id: str
) -> list[dict]:
data = await store.get(_staged_attachments_key(room_id, user_id))
if not isinstance(data, dict):
return []
attachments = data.get("attachments")
if not isinstance(attachments, list):
return []
return [attachment for attachment in attachments if isinstance(attachment, dict)]
async def add_staged_attachment(
store: StateStore, room_id: str, user_id: str, attachment: dict
) -> None:
async with _staged_attachments_lock(room_id, user_id):
attachments = await get_staged_attachments(store, room_id, user_id)
attachments.append(attachment)
await store.set(
_staged_attachments_key(room_id, user_id), {"attachments": attachments}
)
async def remove_staged_attachment_at(
store: StateStore, room_id: str, user_id: str, index: int
) -> dict | None:
async with _staged_attachments_lock(room_id, user_id):
attachments = await get_staged_attachments(store, room_id, user_id)
if index < 0 or index >= len(attachments):
return None
removed = attachments.pop(index)
if attachments:
await store.set(
_staged_attachments_key(room_id, user_id), {"attachments": attachments}
)
else:
await store.delete(_staged_attachments_key(room_id, user_id))
return removed
async def clear_staged_attachments(
store: StateStore, room_id: str, user_id: str
) -> None:
async with _staged_attachments_lock(room_id, user_id):
await store.delete(_staged_attachments_key(room_id, user_id))