feat(backend): feed of deleted and edited messages with bulk deletions grouped and a shared seen marker
This commit is contained in:
1 parent
45c19cac20
commit
83c57ac96b
6 files changed
+657
No files matched your search
@@ -1,3 +1,5 @@
|
||||
from datetime import datetime
|
||||
|
||||
import asyncpg
|
||||
|
||||
from utils.policy.models import FolderSpec
|
||||
@@ -331,6 +333,12 @@ async def get_deleted_messages(
|
||||
f"ORDER BY deleted_at DESC LIMIT ${len(params) - 1} OFFSET ${len(params)}",
|
||||
*params,
|
||||
)
|
||||
return await _single_views(pool, account_id, rows)
|
||||
|
||||
|
||||
async def _single_views(
|
||||
pool: asyncpg.Pool, account_id: int, rows: list[asyncpg.Record]
|
||||
) -> list[MessageView]:
|
||||
media_by_key = await _media_map(pool, account_id, rows)
|
||||
views: list[MessageView] = []
|
||||
for row in rows:
|
||||
@@ -341,6 +349,67 @@ async def get_deleted_messages(
|
||||
return views
|
||||
|
||||
|
||||
async def _rows_at(
|
||||
pool: asyncpg.Pool, account_id: int, keys: list[tuple[int, int, datetime]]
|
||||
) -> list[asyncpg.Record]:
|
||||
if not keys:
|
||||
return []
|
||||
params: list[object] = [account_id]
|
||||
clauses: list[str] = []
|
||||
for key in keys:
|
||||
params.extend(key)
|
||||
n = len(params)
|
||||
clauses.append(
|
||||
f"(chat_id = ${n - 2} AND message_id = ${n - 1} AND date = ${n})"
|
||||
)
|
||||
return await pool.fetch(
|
||||
f"SELECT {_MESSAGE_COLS} FROM messages " # noqa: S608
|
||||
f"WHERE account_id = $1 AND ({' OR '.join(clauses)})",
|
||||
*params,
|
||||
)
|
||||
|
||||
|
||||
async def get_messages_at(
|
||||
pool: asyncpg.Pool, account_id: int, keys: list[tuple[int, int, datetime | None]]
|
||||
) -> dict[tuple[int, int], MessageView]:
|
||||
dated = list(
|
||||
dict.fromkeys((chat, message, date) for chat, message, date in keys if date)
|
||||
)
|
||||
rows = await _rows_at(pool, account_id, dated)
|
||||
views = {
|
||||
(view.chat_id, view.message_id): view
|
||||
for view in await _single_views(pool, account_id, rows)
|
||||
}
|
||||
for chat_id, message_id, _ in keys:
|
||||
if (chat_id, message_id) not in views:
|
||||
view = await get_message(pool, account_id, chat_id, message_id)
|
||||
if view is not None:
|
||||
views[chat_id, message_id] = view
|
||||
return views
|
||||
|
||||
|
||||
async def get_deleted_between( # noqa: PLR0913
|
||||
pool: asyncpg.Pool,
|
||||
account_id: int,
|
||||
chat_id: int,
|
||||
since: datetime,
|
||||
until: datetime,
|
||||
limit: int,
|
||||
before: tuple[datetime, int] | None = None,
|
||||
) -> list[MessageView]:
|
||||
params: list[object] = [account_id, chat_id, since, until, limit]
|
||||
where = "account_id = $1 AND chat_id = $2 AND deleted_at BETWEEN $3 AND $4"
|
||||
if before is not None:
|
||||
params.extend(before)
|
||||
where += " AND (date, message_id) < ($6, $7)"
|
||||
rows = await pool.fetch(
|
||||
f"SELECT {_MESSAGE_COLS} FROM messages WHERE {where} " # noqa: S608
|
||||
"ORDER BY date DESC, message_id DESC LIMIT $5",
|
||||
*params,
|
||||
)
|
||||
return await _single_views(pool, account_id, rows)
|
||||
|
||||
|
||||
async def get_message_versions(
|
||||
pool: asyncpg.Pool, account_id: int, chat_id: int, message_id: int
|
||||
) -> list[MessageVersionView]:
|
||||
|
||||
Reference in new issue
Block a user