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.
This commit is contained in:
parent
441f498d6f
commit
928bb16da1
5 changed files with 19 additions and 6 deletions
|
|
@ -359,7 +359,7 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
print(f"[{self.name}] Failed to send image attachment, falling back to URL: {e}")
|
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)
|
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."""
|
"""Send typing indicator."""
|
||||||
if self._client:
|
if self._client:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -419,7 +419,7 @@ class HomeAssistantAdapter(BasePlatformAdapter):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return SendResult(success=False, error=str(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."""
|
"""No typing indicator for Home Assistant."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ class SlackAdapter(BasePlatformAdapter):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return SendResult(success=False, error=str(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."""
|
"""Slack doesn't have a direct typing indicator API for bots."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
audio_path: str,
|
audio_path: str,
|
||||||
caption: Optional[str] = None,
|
caption: Optional[str] = None,
|
||||||
reply_to: Optional[str] = None,
|
reply_to: Optional[str] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send audio as a native Telegram voice message or audio file."""
|
"""Send audio as a native Telegram voice message or audio file."""
|
||||||
if not self._bot:
|
if not self._bot:
|
||||||
|
|
@ -302,19 +303,23 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
with open(audio_path, "rb") as audio_file:
|
with open(audio_path, "rb") as audio_file:
|
||||||
# .ogg files -> send as voice (round playable bubble)
|
# .ogg files -> send as voice (round playable bubble)
|
||||||
if audio_path.endswith(".ogg") or audio_path.endswith(".opus"):
|
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(
|
msg = await self._bot.send_voice(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
voice=audio_file,
|
voice=audio_file,
|
||||||
caption=caption[:1024] if caption else None,
|
caption=caption[:1024] if caption else None,
|
||||||
reply_to_message_id=int(reply_to) if reply_to 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:
|
else:
|
||||||
# .mp3 and others -> send as audio file
|
# .mp3 and others -> send as audio file
|
||||||
|
_audio_thread = metadata.get("thread_id") if metadata else None
|
||||||
msg = await self._bot.send_audio(
|
msg = await self._bot.send_audio(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
audio=audio_file,
|
audio=audio_file,
|
||||||
caption=caption[:1024] if caption else None,
|
caption=caption[:1024] if caption else None,
|
||||||
reply_to_message_id=int(reply_to) if reply_to 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))
|
return SendResult(success=True, message_id=str(msg.message_id))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -355,6 +360,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
image_url: str,
|
image_url: str,
|
||||||
caption: Optional[str] = None,
|
caption: Optional[str] = None,
|
||||||
reply_to: Optional[str] = None,
|
reply_to: Optional[str] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send an image natively as a Telegram photo.
|
"""Send an image natively as a Telegram photo.
|
||||||
|
|
||||||
|
|
@ -366,11 +372,13 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Telegram can send photos directly from URLs (up to ~5MB)
|
# 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(
|
msg = await self._bot.send_photo(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
photo=image_url,
|
photo=image_url,
|
||||||
caption=caption[:1024] if caption else None, # Telegram caption limit
|
caption=caption[:1024] if caption else None, # Telegram caption limit
|
||||||
reply_to_message_id=int(reply_to) if reply_to else None,
|
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))
|
return SendResult(success=True, message_id=str(msg.message_id))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -401,17 +409,20 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
animation_url: str,
|
animation_url: str,
|
||||||
caption: Optional[str] = None,
|
caption: Optional[str] = None,
|
||||||
reply_to: Optional[str] = None,
|
reply_to: Optional[str] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send an animated GIF natively as a Telegram animation (auto-plays inline)."""
|
"""Send an animated GIF natively as a Telegram animation (auto-plays inline)."""
|
||||||
if not self._bot:
|
if not self._bot:
|
||||||
return SendResult(success=False, error="Not connected")
|
return SendResult(success=False, error="Not connected")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
_anim_thread = metadata.get("thread_id") if metadata else None
|
||||||
msg = await self._bot.send_animation(
|
msg = await self._bot.send_animation(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
animation=animation_url,
|
animation=animation_url,
|
||||||
caption=caption[:1024] if caption else None,
|
caption=caption[:1024] if caption else None,
|
||||||
reply_to_message_id=int(reply_to) if reply_to 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))
|
return SendResult(success=True, message_id=str(msg.message_id))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -419,13 +430,15 @@ class TelegramAdapter(BasePlatformAdapter):
|
||||||
# Fallback: try as a regular photo
|
# Fallback: try as a regular photo
|
||||||
return await self.send_image(chat_id, animation_url, caption, reply_to)
|
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."""
|
"""Send typing indicator."""
|
||||||
if self._bot:
|
if self._bot:
|
||||||
try:
|
try:
|
||||||
|
_typing_thread = metadata.get("thread_id") if metadata else None
|
||||||
await self._bot.send_chat_action(
|
await self._bot.send_chat_action(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
action="typing"
|
action="typing",
|
||||||
|
message_thread_id=int(_typing_thread) if _typing_thread else None,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Ignore typing indicator failures
|
pass # Ignore typing indicator failures
|
||||||
|
|
|
||||||
|
|
@ -493,7 +493,7 @@ class WhatsAppAdapter(BasePlatformAdapter):
|
||||||
file_name or os.path.basename(file_path),
|
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."""
|
"""Send typing indicator via bridge."""
|
||||||
if not self._running:
|
if not self._running:
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue