From 04b33e708de97fbb07a78b92374755d36082fc73 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 10 Oct 2026 14:13:40 +0200 Subject: [PATCH] feat: show main menu with version notice --- VERSION | 2 +- bot.py | 34 +++++++++++++++++++++++++--------- tests/test_release_help.py | 13 ++++++++++--- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/VERSION b/VERSION index 216bf20..e25e9f6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0+45 +0.1.0+46 diff --git a/bot.py b/bot.py index 9d42d21..6a27935 100644 --- a/bot.py +++ b/bot.py @@ -240,27 +240,38 @@ async def report_error(message: Message, stage: str, exc: Exception) -> None: ) -async def notify_development_deploy(bot: Bot) -> None: +async def notify_development_deploy( + bot: Bot, state: FSMContext | None = None, user_id: int | None = None +) -> bool: if not is_development_environment(): - return + return False chat_id = os.getenv("DEV_CHAT_ID", "").strip() if not chat_id: logger.warning("DEV_CHAT_ID is missing; no version notice will be sent") - return + return False async with _deploy_notice_lock: previous = await asyncio.to_thread(get_deploy_notice_version) if previous == VERSION: - return + return False try: await asyncio.wait_for( - bot.send_message(chat_id=int(chat_id), text=f"🚀 Бот обновлён\nВерсия: {VERSION}"), + bot.send_message( + chat_id=int(chat_id), + text=f"🚀 Бот обновлён\nВерсия: {VERSION}", + reply_markup=main_menu_keyboard(), + ), timeout=8, ) except Exception as exc: logger.error("Development deploy notice failed (%s): %s", type(exc).__name__, str(exc)[:160]) - return + return False await asyncio.to_thread(set_deploy_notice_version, VERSION) + user_is_recipient = user_id is not None and str(user_id) == chat_id + if state is not None and user_is_recipient: + await state.clear() + await state.set_state(BotMode.lobby) logger.info("Development deploy notice sent: version=%s", VERSION) + return user_is_recipient async def send_rich_message( @@ -985,7 +996,8 @@ async def _generate_posts_from_images(message: Message, images, request: str, st async def _handle_image_message(message: Message, bot: Bot, state: FSMContext) -> None: - await notify_development_deploy(bot) + if (await notify_development_deploy(bot, state, message.from_user.id if message.from_user else None)) is True: + return with diagnostic_operation(): status = None try: @@ -1096,7 +1108,8 @@ async def transcribe_voice(message: Message, bot: Bot, state: FSMContext) -> Non reply_markup=keyboard_for_mode(mode), ) return - await notify_development_deploy(bot) + if (await notify_development_deploy(bot, state, message.from_user.id if message.from_user else None)) is True: + return with diagnostic_operation(): status = await OperationStatus.start(message, "⏳ Подготавливаю аудио…") try: @@ -1151,7 +1164,10 @@ async def handle_command_text(message: Message, state: FSMContext) -> None: @router.message(F.text & ~F.text.startswith("/")) async def handle_text(message: Message, state: FSMContext) -> None: - await notify_development_deploy(message.bot) + if message.bot is not None and (await notify_development_deploy( + message.bot, state, message.from_user.id if message.from_user else None + )) is True: + return text = (message.text or "").strip() if not text: return diff --git a/tests/test_release_help.py b/tests/test_release_help.py index f9778b6..49a736a 100644 --- a/tests/test_release_help.py +++ b/tests/test_release_help.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio import unittest from datetime import datetime +from typing import Any, cast from unittest.mock import AsyncMock, patch from aiogram.types import Chat, Message @@ -27,6 +28,7 @@ class _StubState: class DeployNoticeTests(unittest.IsolatedAsyncioTestCase): async def test_sends_once_per_new_version_only_in_development(self): fake_bot = AsyncMock() + state = _StubState("generation") with ( patch.object(bot, "DEPLOY_ENV", "development"), patch.object(bot, "VERSION", "0.1.0+5"), @@ -35,9 +37,14 @@ class DeployNoticeTests(unittest.IsolatedAsyncioTestCase): patch.object(bot, "set_deploy_notice_version"), patch.object(bot.asyncio, "to_thread", new=AsyncMock(side_effect=["0.1.0+4", None, "0.1.0+5"])), ): - await bot.notify_development_deploy(fake_bot) - await bot.notify_development_deploy(fake_bot) - fake_bot.send_message.assert_awaited_once_with(chat_id=2201809732, text="🚀 Бот обновлён\nВерсия: 0.1.0+5") + self.assertTrue(await bot.notify_development_deploy(fake_bot, cast(Any, state), 2201809732)) + self.assertFalse(await bot.notify_development_deploy(fake_bot)) + fake_bot.send_message.assert_awaited_once_with( + chat_id=2201809732, + text="🚀 Бот обновлён\nВерсия: 0.1.0+5", + reply_markup=bot.main_menu_keyboard(), + ) + self.assertEqual(state.value, bot.BotMode.lobby.state) async def test_does_not_send_outside_development(self): fake_bot = AsyncMock()