diff --git a/codex_telegram_bridge/src/codex_telegram_bridge/constants.py b/codex_telegram_bridge/src/codex_telegram_bridge/constants.py index 9347c22..219b12c 100644 --- a/codex_telegram_bridge/src/codex_telegram_bridge/constants.py +++ b/codex_telegram_bridge/src/codex_telegram_bridge/constants.py @@ -3,5 +3,4 @@ from __future__ import annotations from pathlib import Path TELEGRAM_HARD_LIMIT = 4096 -DEFAULT_CHUNK_LEN = 3500 # leave room for formatting / safety TELEGRAM_CONFIG_PATH = Path.home() / ".codex" / "telegram.toml" diff --git a/codex_telegram_bridge/src/codex_telegram_bridge/exec_bridge.py b/codex_telegram_bridge/src/codex_telegram_bridge/exec_bridge.py index d92b71e..4e18fff 100644 --- a/codex_telegram_bridge/src/codex_telegram_bridge/exec_bridge.py +++ b/codex_telegram_bridge/src/codex_telegram_bridge/exec_bridge.py @@ -63,6 +63,8 @@ def _one_line(text: Optional[str]) -> str: TELEGRAM_TEXT_LIMIT = TELEGRAM_HARD_LIMIT +TELEGRAM_MARKDOWN_LIMIT = 3500 +ELLIPSIS = "…" def _clamp_tg_text(text: str, limit: int = TELEGRAM_TEXT_LIMIT) -> str: @@ -70,6 +72,30 @@ def _clamp_tg_text(text: str, limit: int = TELEGRAM_TEXT_LIMIT) -> str: return text return text[: limit - 20] + "\n...(truncated)" +def _send_markdown( + bot: TelegramClient, + *, + chat_id: int, + text: str, + reply_to_message_id: Optional[int] = None, + disable_notification: bool = False, +) -> Dict[str, Any]: + rendered_text, entities = render_markdown(text) + if len(rendered_text) > TELEGRAM_MARKDOWN_LIMIT: + sep = "\n" + ELLIPSIS + "\n" + lines = rendered_text.splitlines() + tail = lines[-1] if lines else "" + max_head = max(0, TELEGRAM_MARKDOWN_LIMIT - len(sep) - len(tail)) + rendered_text = rendered_text[:max_head] + sep + tail + entities = None + return bot.send_message( + chat_id=chat_id, + text=rendered_text, + entities=entities or None, + reply_to_message_id=reply_to_message_id, + disable_notification=disable_notification, + ) + class ProgressEditor: def __init__( @@ -488,11 +514,7 @@ def run( except Exception as ee: log(f"[handle] failed to edit progress into error: {ee}") - sent_msgs = bot.send_message_markdown_chunked( - chat_id=chat_id, - text=err, - reply_to_message_id=user_msg_id, - ) + _send_markdown(bot, chat_id=chat_id, text=err, reply_to_message_id=user_msg_id) log( "[handle] error " f"chat_id={chat_id} user_msg_id={user_msg_id} resume_session={resume_session!r} err={e}" @@ -511,11 +533,7 @@ def run( can_edit_final = progress_id is not None and len(final_text) <= TELEGRAM_TEXT_LIMIT if loud_final or not can_edit_final: - sent_msgs = bot.send_message_markdown_chunked( - chat_id=chat_id, - text=final_md, - reply_to_message_id=user_msg_id, - ) + _send_markdown(bot, chat_id=chat_id, text=final_md, reply_to_message_id=user_msg_id) if progress_id is not None: try: bot.delete_message(chat_id=chat_id, message_id=progress_id) diff --git a/codex_telegram_bridge/src/codex_telegram_bridge/telegram_client.py b/codex_telegram_bridge/src/codex_telegram_bridge/telegram_client.py index f7eb625..e48b596 100644 --- a/codex_telegram_bridge/src/codex_telegram_bridge/telegram_client.py +++ b/codex_telegram_bridge/src/codex_telegram_bridge/telegram_client.py @@ -5,12 +5,6 @@ import urllib.error import urllib.request from typing import Any, Dict, List, Optional -from .constants import DEFAULT_CHUNK_LEN, TELEGRAM_HARD_LIMIT -from .rendering import render_markdown - -ELLIPSIS = "…" - - class TelegramClient: """ Minimal Telegram Bot API client using standard library (no requests dependency). @@ -100,32 +94,3 @@ class TelegramClient: } res = self._call("deleteMessage", params) return bool(res) - - def send_message_markdown_chunked( - self, - chat_id: int, - text: str, - reply_to_message_id: Optional[int] = None, - disable_notification: bool = False, - chunk_len: int = DEFAULT_CHUNK_LEN, - ) -> List[Dict[str, Any]]: - rendered_text, entities = render_markdown(text) - limit = min(chunk_len, TELEGRAM_HARD_LIMIT) - if len(rendered_text) > limit: - # If we truncate, drop entities to avoid offset gymnastics. - # Preserve the final `resume: `...`` line if present. - sep = "\n" + ELLIPSIS + "\n" - lines = rendered_text.splitlines() - tail = lines[-1] if lines else "" - max_head = max(0, limit - len(sep) - len(tail)) - rendered_text = "".join([rendered_text[:max_head], sep, tail]) - entities = None - - msg = self.send_message( - chat_id=chat_id, - text=rendered_text, - reply_to_message_id=reply_to_message_id, - disable_notification=disable_notification, - entities=entities or None, - ) - return [msg]