feat(backend): get_feed mcp tool reads the feed of deleted and edited messages

This commit is contained in:
hh committed 2026-10-19 02:59:07 +00:00
1 parent 83c57ac96b
commit 395d58464d
1 file changed
+39 -2
+39 -2
View File
@@ -1,3 +1,4 @@
import re
from collections.abc import Sequence
from datetime import datetime
from typing import Any
@@ -23,6 +24,7 @@ from utils.files import resolve_mime
from utils.read import (
annotations,
chats,
feed,
media,
peers,
people,
@@ -32,6 +34,7 @@ from utils.read import (
watches,
)
from utils.read.accounts import self_user_id, unknown_account_hint
from utils.read.feed import CURSOR_PATTERN, FeedChatKind, FeedFilter, FeedKind
from utils.read.models import DEFAULT_LIMIT, Page
from utils.read.period import DEFAULT_TZ, MAX_DAYS, known_timezone
from utils.read.read_receipts import read_info
@@ -73,8 +76,10 @@ Typical flows:
transcripts; supports chat/sender/date filters and regex).
- People: `get_person` gives one person in full: profile changes, shared groups,
joins and leaves, deleted message count, the private chat.
- Forensics: `get_deleted_messages` and `get_message_versions` recover content
removed or edited in Telegram but kept in the archive.
- Forensics: `get_feed` lists what was deleted or edited in Telegram across
all chats, newest first, with the text before and after each edit; a bulk
deletion is one item with `message_count`. `get_deleted_messages` and
`get_message_versions` recover the content of one chat or one message.
- Files: `download_media` gets any message attachment (photo, video, voice,
document, ...). It pulls the file from Telegram if the archive lacks it and
returns a public link valid 24h that needs no auth (`curl -O <link>`), plus
@@ -255,6 +260,38 @@ async def get_deleted_messages(
)
@mcp.tool
async def get_feed(
account_id: int,
kind: FeedKind = FeedKind.ALL,
since: datetime | None = None,
chat_id: int | None = None,
chat_kind: FeedChatKind | None = None,
limit: int = DEFAULT_LIMIT,
cursor: str | None = None,
) -> dict[str, Any]:
"""Deleted and edited messages across chats, newest first.
`kind` picks deleted, edited or all; `since` keeps items at or after that
time; `chat_id` or `chat_kind` (dm, group, channel) narrow it down. Edited
items carry `before` and `after` texts. A deleted item with
`message_count` above 1 is a bulk deletion in one chat; read its messages
with `get_deleted_messages` for that chat. Pass `next_cursor` back as
`cursor` for the next page.
"""
if cursor is not None and re.fullmatch(CURSOR_PATTERN, cursor) is None:
msg = "cursor must be a next_cursor returned by get_feed"
raise ToolError(msg)
page = await feed.list_feed(
await _pool(),
account_id,
FeedFilter(kind=kind, chat_id=chat_id, chat_kind=chat_kind, since=since),
limit=limit,
cursor=cursor,
)
return page.model_dump(mode="json")
@mcp.tool
async def get_message_versions(
account_id: int, chat_id: int, message_id: int