From 928bb16da1cb259e1e8c258be0e4d933a823e68b Mon Sep 17 00:00:00 2001 From: teknium1 Date: Tue, 10 Mar 2026 06:26:16 -0700 Subject: [PATCH] fix: forward thread_id to Telegram adapter + update send_typing signatures Part 2 of thread_id forum topic fix: add metadata param to send_voice, send_image, send_animation, send_typing in Telegram adapter and pass message_thread_id to all Bot API calls. Update send_typing signature in Discord, Slack, WhatsApp, HomeAssistant for compatibility. Based on the fix proposed by @Bitstreamono in PR #656. --- gateway/platforms/discord.py | 2 +- gateway/platforms/homeassistant.py | 2 +- gateway/platforms/slack.py | 2 +- gateway/platforms/telegram.py | 17 +++++++++++++++-- gateway/platforms/whatsapp.py | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/gateway/platforms/discord.py b/gateway/platforms/discord.py index 905e20d6..39267fba 100644 --- a/gateway/platforms/discord.py +++ b/gateway/platforms/discord.py @@ -359,7 +359,7 @@ class DiscordAdapter(BasePlatformAdapter): print(f"[{self.name}] Failed to send image attachment, falling back to URL: {e}") return await super().send_image(chat_id, image_url, caption, reply_to) - async def send_typing(self, chat_id: str) -> None: + async def send_typing(self, chat_id: str, metadata=None) -> None: """Send typing indicator.""" if self._client: try: diff --git a/gateway/platforms/homeassistant.py b/gateway/platforms/homeassistant.py index a900ef3b..93047060 100644 --- a/gateway/platforms/homeassistant.py +++ b/gateway/platforms/homeassistant.py @@ -419,7 +419,7 @@ class HomeAssistantAdapter(BasePlatformAdapter): except Exception as e: return SendResult(success=False, error=str(e)) - async def send_typing(self, chat_id: str) -> None: + async def send_typing(self, chat_id: str, metadata=None) -> None: """No typing indicator for Home Assistant.""" pass diff --git a/gateway/platforms/slack.py b/gateway/platforms/slack.py index 020843d3..3449971f 100644 --- a/gateway/platforms/slack.py +++ b/gateway/platforms/slack.py @@ -185,7 +185,7 @@ class SlackAdapter(BasePlatformAdapter): except Exception as e: return SendResult(success=False, error=str(e)) - async def send_typing(self, chat_id: str) -> None: + async def send_typing(self, chat_id: str, metadata=None) -> None: """Slack doesn't have a direct typing indicator API for bots.""" pass diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index 2100ed61..1ec64b4e 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -289,6 +289,7 @@ class TelegramAdapter(BasePlatformAdapter): audio_path: str, caption: Optional[str] = None, reply_to: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, ) -> SendResult: """Send audio as a native Telegram voice message or audio file.""" if not self._bot: @@ -302,19 +303,23 @@ class TelegramAdapter(BasePlatformAdapter): with open(audio_path, "rb") as audio_file: # .ogg files -> send as voice (round playable bubble) if audio_path.endswith(".ogg") or audio_path.endswith(".opus"): + _voice_thread = metadata.get("thread_id") if metadata else None msg = await self._bot.send_voice( chat_id=int(chat_id), voice=audio_file, caption=caption[:1024] if caption else None, reply_to_message_id=int(reply_to) if reply_to else None, + message_thread_id=int(_voice_thread) if _voice_thread else None, ) else: # .mp3 and others -> send as audio file + _audio_thread = metadata.get("thread_id") if metadata else None msg = await self._bot.send_audio( chat_id=int(chat_id), audio=audio_file, caption=caption[:1024] if caption else None, reply_to_message_id=int(reply_to) if reply_to else None, + message_thread_id=int(_audio_thread) if _audio_thread else None, ) return SendResult(success=True, message_id=str(msg.message_id)) except Exception as e: @@ -355,6 +360,7 @@ class TelegramAdapter(BasePlatformAdapter): image_url: str, caption: Optional[str] = None, reply_to: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, ) -> SendResult: """Send an image natively as a Telegram photo. @@ -366,11 +372,13 @@ class TelegramAdapter(BasePlatformAdapter): try: # Telegram can send photos directly from URLs (up to ~5MB) + _photo_thread = metadata.get("thread_id") if metadata else None msg = await self._bot.send_photo( chat_id=int(chat_id), photo=image_url, caption=caption[:1024] if caption else None, # Telegram caption limit reply_to_message_id=int(reply_to) if reply_to else None, + message_thread_id=int(_photo_thread) if _photo_thread else None, ) return SendResult(success=True, message_id=str(msg.message_id)) except Exception as e: @@ -401,17 +409,20 @@ class TelegramAdapter(BasePlatformAdapter): animation_url: str, caption: Optional[str] = None, reply_to: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, ) -> SendResult: """Send an animated GIF natively as a Telegram animation (auto-plays inline).""" if not self._bot: return SendResult(success=False, error="Not connected") try: + _anim_thread = metadata.get("thread_id") if metadata else None msg = await self._bot.send_animation( chat_id=int(chat_id), animation=animation_url, caption=caption[:1024] if caption else None, reply_to_message_id=int(reply_to) if reply_to else None, + message_thread_id=int(_anim_thread) if _anim_thread else None, ) return SendResult(success=True, message_id=str(msg.message_id)) except Exception as e: @@ -419,13 +430,15 @@ class TelegramAdapter(BasePlatformAdapter): # Fallback: try as a regular photo return await self.send_image(chat_id, animation_url, caption, reply_to) - async def send_typing(self, chat_id: str) -> None: + async def send_typing(self, chat_id: str, metadata: Optional[Dict[str, Any]] = None) -> None: """Send typing indicator.""" if self._bot: try: + _typing_thread = metadata.get("thread_id") if metadata else None await self._bot.send_chat_action( chat_id=int(chat_id), - action="typing" + action="typing", + message_thread_id=int(_typing_thread) if _typing_thread else None, ) except Exception: pass # Ignore typing indicator failures diff --git a/gateway/platforms/whatsapp.py b/gateway/platforms/whatsapp.py index 285a89ee..f2000add 100644 --- a/gateway/platforms/whatsapp.py +++ b/gateway/platforms/whatsapp.py @@ -493,7 +493,7 @@ class WhatsAppAdapter(BasePlatformAdapter): file_name or os.path.basename(file_path), ) - async def send_typing(self, chat_id: str) -> None: + async def send_typing(self, chat_id: str, metadata=None) -> None: """Send typing indicator via bridge.""" if not self._running: return