feat: add api and mcp

This commit is contained in:
hh
2026-05-30 01:32:35 +02:00
parent 6a5cde6ae4
commit c40e720163
30 changed files with 2354 additions and 31 deletions
+105
View File
@@ -0,0 +1,105 @@
import asyncpg
from utils.read.models import ChatListItem, MessageVersionView, MessageView, Page
_MESSAGE_COLS = (
"chat_id, message_id, date, sender_id, text, "
"has_media, is_self_destruct, edited_at, deleted_at"
)
def _peer_title(
first: str | None, last: str | None, username: str | None
) -> str | None:
name = " ".join(part for part in (first, last) if part)
return name or username
async def list_chats(
pool: asyncpg.Pool, account_id: int, page: Page
) -> list[ChatListItem]:
rows = await pool.fetch(
"SELECT m.chat_id, count(*) AS message_count, max(m.date) AS last_date, "
"(SELECT p.first_name FROM peers p "
"WHERE p.account_id = $1 AND p.peer_id = m.chat_id) AS first_name, "
"(SELECT p.last_name FROM peers p "
"WHERE p.account_id = $1 AND p.peer_id = m.chat_id) AS last_name, "
"(SELECT p.username FROM peers p "
"WHERE p.account_id = $1 AND p.peer_id = m.chat_id) AS username, "
"(SELECT ch.title FROM chat_history ch "
"WHERE ch.account_id = $1 AND ch.chat_id = m.chat_id "
"AND ch.title IS NOT NULL ORDER BY ch.ts DESC LIMIT 1) AS group_title "
"FROM messages m WHERE m.account_id = $1 "
"GROUP BY m.chat_id ORDER BY last_date DESC LIMIT $2 OFFSET $3",
account_id,
page.capped_limit,
page.offset,
)
items = []
for row in rows:
title = row["group_title"] or _peer_title(
row["first_name"], row["last_name"], row["username"]
)
items.append(
ChatListItem(
chat_id=row["chat_id"],
title=title,
message_count=row["message_count"],
last_date=row["last_date"],
)
)
return items
async def get_chat_history(
pool: asyncpg.Pool,
account_id: int,
chat_id: int,
page: Page,
*,
include_deleted: bool = True,
) -> list[MessageView]:
where = "account_id = $1 AND chat_id = $2"
if not include_deleted:
where += " AND deleted_at IS NULL"
rows = await pool.fetch(
f"SELECT {_MESSAGE_COLS} FROM messages WHERE {where} " # noqa: S608
"ORDER BY date DESC, message_id DESC LIMIT $3 OFFSET $4",
account_id,
chat_id,
page.capped_limit,
page.offset,
)
return [MessageView(**dict(row)) for row in rows]
async def get_deleted_messages(
pool: asyncpg.Pool, account_id: int, page: Page, *, chat_id: int | None = None
) -> list[MessageView]:
params: list[object] = [account_id]
where = "account_id = $1 AND deleted_at IS NOT NULL"
if chat_id is not None:
params.append(chat_id)
where += f" AND chat_id = ${len(params)}"
params.append(page.capped_limit)
params.append(page.offset)
rows = await pool.fetch(
f"SELECT {_MESSAGE_COLS} FROM messages WHERE {where} " # noqa: S608
f"ORDER BY deleted_at DESC LIMIT ${len(params) - 1} OFFSET ${len(params)}",
*params,
)
return [MessageView(**dict(row)) for row in rows]
async def get_message_versions(
pool: asyncpg.Pool, account_id: int, chat_id: int, message_id: int
) -> list[MessageVersionView]:
rows = await pool.fetch(
"SELECT observed_at, edit_date, text FROM message_versions "
"WHERE account_id = $1 AND chat_id = $2 AND message_id = $3 "
"ORDER BY observed_at",
account_id,
chat_id,
message_id,
)
return [MessageVersionView(**dict(row)) for row in rows]