feat: web UI chat render, panels, presence + analytics

This commit is contained in:
h
2026-05-31 19:41:01 +02:00
parent 75425d1bee
commit ed469ba8dd
83 changed files with 6034 additions and 136 deletions
+32
View File
@@ -0,0 +1,32 @@
import asyncpg
from utils.read.message_view import _media_kind, _peer_name, load_raw
from utils.read.models import PinnedView
_PINNED_SQL = (
"SELECT raw FROM messages "
"WHERE account_id = $1 AND chat_id = $2 "
"AND raw->>'service' LIKE '%PINNED_MESSAGE%' "
"ORDER BY date DESC, message_id DESC LIMIT 1"
)
async def get_pinned(
pool: asyncpg.Pool, account_id: int, chat_id: int
) -> PinnedView | None:
row = await pool.fetchrow(_PINNED_SQL, account_id, chat_id)
if row is None:
return None
pinned = load_raw(row["raw"]).get("pinned_message")
if not isinstance(pinned, dict):
return None
message_id = pinned.get("id")
if message_id is None:
return None
sender = pinned.get("from_user")
return PinnedView(
message_id=message_id,
text=pinned.get("text") or pinned.get("caption"),
media_kind=_media_kind(pinned),
sender_name=_peer_name(sender) if isinstance(sender, dict) else None,
)