From ff37abdb011d00a9d58e5ccbb252105203476e3d Mon Sep 17 00:00:00 2001 From: Ivan Kolodrivskyi Date: Thu, 9 Apr 2026 08:16:44 +0300 Subject: [PATCH 1/2] fix: return JSON from get_messages to preserve multi-line message text The pipe-delimited text format (ID: N | ... | Message: ) breaks when messages contain newlines, since \n serves as both record separator and can appear inside message text. Downstream parsers that split on \n only capture the first line Switch to a JSON array output with fields: id, sender, date, text, reply_to (optional), and engagement (optional, with views/forwards/reactions) This is a breaking change for MCP clients that parse the old text format. Since MCP tool results are typically consumed by LLMs which handle JSON natively, this should be transparent for most consumers --- main.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/main.py b/main.py index 77a4470..993d7c3 100644 --- a/main.py +++ b/main.py @@ -727,19 +727,34 @@ async def get_messages(chat_id: Union[int, str], page: int = 1, page_size: int = messages = await client.get_messages(entity, limit=page_size, add_offset=offset) if not messages: return "No messages found for this page." - lines = [] + result = [] for msg in messages: sender_name = get_sender_name(msg) - reply_info = "" + entry = { + "id": msg.id, + "sender": sender_name, + "date": str(msg.date), + "text": msg.message, + } if msg.reply_to and msg.reply_to.reply_to_msg_id: - reply_info = f" | reply to {msg.reply_to.reply_to_msg_id}" - - engagement_info = get_engagement_info(msg) - - lines.append( - f"ID: {msg.id} | {sender_name} | Date: {msg.date}{reply_info}{engagement_info} | Message: {msg.message}" - ) - return "\n".join(lines) + entry["reply_to"] = msg.reply_to.reply_to_msg_id + # Engagement metrics (views, forwards, reactions) + engagement = {} + views = getattr(msg, "views", None) + if views is not None: + engagement["views"] = views + forwards = getattr(msg, "forwards", None) + if forwards is not None: + engagement["forwards"] = forwards + reactions = getattr(msg, "reactions", None) + if reactions is not None: + results = getattr(reactions, "results", None) + if results: + engagement["reactions"] = sum(getattr(r, "count", 0) or 0 for r in results) + if engagement: + entry["engagement"] = engagement + result.append(entry) + return json.dumps(result, ensure_ascii=False, default=json_serializer) except Exception as e: return log_and_format_error( "get_messages", e, chat_id=chat_id, page=page, page_size=page_size From b38051a9eeb04188d6a52455b57f2b9c2b497a34 Mon Sep 17 00:00:00 2001 From: Ivan Kolodrivskyi Date: Thu, 9 Apr 2026 08:33:54 +0300 Subject: [PATCH 2/2] fix: escape newlines in get_messages instead of switching to JSON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the JSON output approach with a non-breaking fix: escape newlines in message text (\n → \\n) to preserve the existing pipe-delimited format. This fixes multi-line message parsing without breaking downstream consumers. --- main.py | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/main.py b/main.py index 993d7c3..2d70f0a 100644 --- a/main.py +++ b/main.py @@ -727,34 +727,20 @@ async def get_messages(chat_id: Union[int, str], page: int = 1, page_size: int = messages = await client.get_messages(entity, limit=page_size, add_offset=offset) if not messages: return "No messages found for this page." - result = [] + lines = [] for msg in messages: sender_name = get_sender_name(msg) - entry = { - "id": msg.id, - "sender": sender_name, - "date": str(msg.date), - "text": msg.message, - } + reply_info = "" if msg.reply_to and msg.reply_to.reply_to_msg_id: - entry["reply_to"] = msg.reply_to.reply_to_msg_id - # Engagement metrics (views, forwards, reactions) - engagement = {} - views = getattr(msg, "views", None) - if views is not None: - engagement["views"] = views - forwards = getattr(msg, "forwards", None) - if forwards is not None: - engagement["forwards"] = forwards - reactions = getattr(msg, "reactions", None) - if reactions is not None: - results = getattr(reactions, "results", None) - if results: - engagement["reactions"] = sum(getattr(r, "count", 0) or 0 for r in results) - if engagement: - entry["engagement"] = engagement - result.append(entry) - return json.dumps(result, ensure_ascii=False, default=json_serializer) + reply_info = f" | reply to {msg.reply_to.reply_to_msg_id}" + + engagement_info = get_engagement_info(msg) + safe_text = (msg.message or "").replace("\n", "\\n") + + lines.append( + f"ID: {msg.id} | {sender_name} | Date: {msg.date}{reply_info}{engagement_info} | Message: {safe_text}" + ) + return "\n".join(lines) except Exception as e: return log_and_format_error( "get_messages", e, chat_id=chat_id, page=page, page_size=page_size