from unittest.mock import AsyncMock, MagicMock, patch import pytest from gateway.config import Platform from gateway.platforms.base import MessageEvent, MessageType, SendResult from gateway.session import SessionSource def _voice_event(thread_id=None) -> MessageEvent: return MessageEvent( text="", message_type=MessageType.VOICE, source=SessionSource( platform=Platform.TELEGRAM, chat_id="123", chat_type="dm", thread_id=thread_id, message_id="42", ), message_id="42", ) @pytest.mark.asyncio async def test_pre_stt_ack_is_best_effort_and_platform_side(): from gateway.platforms.telegram import TelegramAdapter adapter = TelegramAdapter.__new__(TelegramAdapter) adapter.send = AsyncMock(return_value=SendResult(success=True, message_id="99")) event = _voice_event() await adapter._send_voice_pre_stt_ack(event) adapter.send.assert_awaited_once_with( "123", "🎧 получил, распознаю", reply_to="42", metadata=None, ) @pytest.mark.asyncio async def test_pre_stt_ack_failure_does_not_raise(): from gateway.platforms.telegram import TelegramAdapter adapter = TelegramAdapter.__new__(TelegramAdapter) adapter.send = AsyncMock(side_effect=RuntimeError("telegram is temporarily unavailable")) await adapter._send_voice_pre_stt_ack(_voice_event()) adapter.send.assert_awaited_once() @pytest.mark.asyncio async def test_voice_handler_sends_ack_before_dispatching_to_gateway(): from gateway.platforms.telegram import TelegramAdapter adapter = TelegramAdapter.__new__(TelegramAdapter) adapter.platform = Platform.TELEGRAM adapter.config = MagicMock() adapter.config.extra = {} order = [] adapter._should_process_message = lambda message: True adapter._apply_telegram_group_observe_attribution = lambda event: event adapter._send_voice_pre_stt_ack = AsyncMock(side_effect=lambda event: order.append("ack")) adapter.handle_message = AsyncMock(side_effect=lambda event: order.append("handle")) file_obj = MagicMock() file_obj.download_as_bytearray = AsyncMock(return_value=bytearray(b"ogg-data")) voice = MagicMock() voice.get_file = AsyncMock(return_value=file_obj) chat = MagicMock() chat.id = 123 chat.type = "private" chat.title = None chat.full_name = "Тохыч" user = MagicMock() user.id = 456 user.full_name = "Тохыч" msg = MagicMock() msg.chat = chat msg.from_user = user msg.message_id = 42 msg.message_thread_id = None msg.is_topic_message = False msg.date = None msg.caption = None msg.text = "" msg.reply_to_message = None msg.sticker = None msg.photo = [] msg.video = None msg.audio = None msg.voice = voice msg.document = None msg.media_group_id = None update = MagicMock() update.message = msg update.update_id = 777 with patch("gateway.platforms.telegram.cache_audio_from_bytes", return_value="/tmp/voice.ogg"): await adapter._handle_media_message(update, MagicMock()) assert order == ["ack", "handle"] handled_event = adapter.handle_message.await_args.args[0] assert handled_event.media_urls == ["/tmp/voice.ogg"] assert handled_event.media_types == ["audio/ogg"]