fix(gateway): pass message_thread_id in send_image_file, send_document, send_video (#2339)
fix(gateway): pass message_thread_id in send_image_file, send_document, send_video
This commit is contained in:
@@ -578,23 +578,26 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
image_path: str,
|
image_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,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send a local image file natively as a Telegram photo."""
|
"""Send a local image file natively as a Telegram photo."""
|
||||||
if not self._bot:
|
if not self._bot:
|
||||||
return SendResult(success=False, error="Not connected")
|
return SendResult(success=False, error="Not connected")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import os
|
import os
|
||||||
if not os.path.exists(image_path):
|
if not os.path.exists(image_path):
|
||||||
return SendResult(success=False, error=f"Image file not found: {image_path}")
|
return SendResult(success=False, error=f"Image file not found: {image_path}")
|
||||||
|
|
||||||
|
_thread = metadata.get("thread_id") if metadata else None
|
||||||
with open(image_path, "rb") as image_file:
|
with open(image_path, "rb") as image_file:
|
||||||
msg = await self._bot.send_photo(
|
msg = await self._bot.send_photo(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
photo=image_file,
|
photo=image_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(_thread) if _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:
|
||||||
@@ -613,6 +616,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
caption: Optional[str] = None,
|
caption: Optional[str] = None,
|
||||||
file_name: Optional[str] = None,
|
file_name: Optional[str] = None,
|
||||||
reply_to: Optional[str] = None,
|
reply_to: Optional[str] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send a document/file natively as a Telegram file attachment."""
|
"""Send a document/file natively as a Telegram file attachment."""
|
||||||
@@ -624,6 +628,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
return SendResult(success=False, error=f"File not found: {file_path}")
|
return SendResult(success=False, error=f"File not found: {file_path}")
|
||||||
|
|
||||||
display_name = file_name or os.path.basename(file_path)
|
display_name = file_name or os.path.basename(file_path)
|
||||||
|
_thread = metadata.get("thread_id") if metadata else None
|
||||||
|
|
||||||
with open(file_path, "rb") as f:
|
with open(file_path, "rb") as f:
|
||||||
msg = await self._bot.send_document(
|
msg = await self._bot.send_document(
|
||||||
@@ -632,6 +637,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
filename=display_name,
|
filename=display_name,
|
||||||
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(_thread) if _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:
|
||||||
@@ -644,6 +650,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
video_path: str,
|
video_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,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send a video natively as a Telegram video message."""
|
"""Send a video natively as a Telegram video message."""
|
||||||
@@ -654,12 +661,14 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
if not os.path.exists(video_path):
|
if not os.path.exists(video_path):
|
||||||
return SendResult(success=False, error=f"Video file not found: {video_path}")
|
return SendResult(success=False, error=f"Video file not found: {video_path}")
|
||||||
|
|
||||||
|
_thread = metadata.get("thread_id") if metadata else None
|
||||||
with open(video_path, "rb") as f:
|
with open(video_path, "rb") as f:
|
||||||
msg = await self._bot.send_video(
|
msg = await self._bot.send_video(
|
||||||
chat_id=int(chat_id),
|
chat_id=int(chat_id),
|
||||||
video=f,
|
video=f,
|
||||||
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(_thread) if _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:
|
||||||
|
|||||||
@@ -147,6 +147,26 @@ class TestTelegramSendImageFile:
|
|||||||
call_kwargs = adapter._bot.send_photo.call_args.kwargs
|
call_kwargs = adapter._bot.send_photo.call_args.kwargs
|
||||||
assert len(call_kwargs["caption"]) == 1024
|
assert len(call_kwargs["caption"]) == 1024
|
||||||
|
|
||||||
|
def test_thread_id_forwarded(self, adapter, tmp_path):
|
||||||
|
"""metadata thread_id is forwarded as message_thread_id (required for Telegram forum groups)."""
|
||||||
|
img = tmp_path / "shot.png"
|
||||||
|
img.write_bytes(b"\x89PNG" + b"\x00" * 50)
|
||||||
|
|
||||||
|
mock_msg = MagicMock()
|
||||||
|
mock_msg.message_id = 43
|
||||||
|
adapter._bot.send_photo = AsyncMock(return_value=mock_msg)
|
||||||
|
|
||||||
|
_run(
|
||||||
|
adapter.send_image_file(
|
||||||
|
chat_id="12345",
|
||||||
|
image_path=str(img),
|
||||||
|
metadata={"thread_id": "789"},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
call_kwargs = adapter._bot.send_photo.call_args.kwargs
|
||||||
|
assert call_kwargs["message_thread_id"] == 789
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Discord send_image_file tests
|
# Discord send_image_file tests
|
||||||
|
|||||||
@@ -557,6 +557,25 @@ class TestSendDocument:
|
|||||||
call_kwargs = connected_adapter._bot.send_document.call_args[1]
|
call_kwargs = connected_adapter._bot.send_document.call_args[1]
|
||||||
assert call_kwargs["reply_to_message_id"] == 50
|
assert call_kwargs["reply_to_message_id"] == 50
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_send_document_thread_id(self, connected_adapter, tmp_path):
|
||||||
|
"""metadata thread_id is forwarded as message_thread_id (required for Telegram forum groups)."""
|
||||||
|
test_file = tmp_path / "report.pdf"
|
||||||
|
test_file.write_bytes(b"%PDF-1.4 data")
|
||||||
|
|
||||||
|
mock_msg = MagicMock()
|
||||||
|
mock_msg.message_id = 103
|
||||||
|
connected_adapter._bot.send_document = AsyncMock(return_value=mock_msg)
|
||||||
|
|
||||||
|
await connected_adapter.send_document(
|
||||||
|
chat_id="12345",
|
||||||
|
file_path=str(test_file),
|
||||||
|
metadata={"thread_id": "789"},
|
||||||
|
)
|
||||||
|
|
||||||
|
call_kwargs = connected_adapter._bot.send_document.call_args[1]
|
||||||
|
assert call_kwargs["message_thread_id"] == 789
|
||||||
|
|
||||||
|
|
||||||
class TestTelegramPhotoBatching:
|
class TestTelegramPhotoBatching:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@@ -654,3 +673,22 @@ class TestSendVideo:
|
|||||||
|
|
||||||
assert result.success is False
|
assert result.success is False
|
||||||
assert "Not connected" in result.error
|
assert "Not connected" in result.error
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_send_video_thread_id(self, connected_adapter, tmp_path):
|
||||||
|
"""metadata thread_id is forwarded as message_thread_id (required for Telegram forum groups)."""
|
||||||
|
test_file = tmp_path / "clip.mp4"
|
||||||
|
test_file.write_bytes(b"\x00\x00\x00\x1c" + b"ftyp" + b"\x00" * 100)
|
||||||
|
|
||||||
|
mock_msg = MagicMock()
|
||||||
|
mock_msg.message_id = 201
|
||||||
|
connected_adapter._bot.send_video = AsyncMock(return_value=mock_msg)
|
||||||
|
|
||||||
|
await connected_adapter.send_video(
|
||||||
|
chat_id="12345",
|
||||||
|
video_path=str(test_file),
|
||||||
|
metadata={"thread_id": "789"},
|
||||||
|
)
|
||||||
|
|
||||||
|
call_kwargs = connected_adapter._bot.send_video.call_args[1]
|
||||||
|
assert call_kwargs["message_thread_id"] == 789
|
||||||
|
|||||||
Reference in New Issue
Block a user