From 8a00d5ac54469f251ee1626862d1288d0766fa51 Mon Sep 17 00:00:00 2001 From: Mikhail Putilovskij Date: Thu, 2 Apr 2026 15:16:39 +0300 Subject: [PATCH] fix(tg): /archive tries delete_forum_topic, falls back with explanation if API rejects --- adapter/telegram/handlers/commands.py | 18 ++++++++++++++---- tests/adapter/telegram/test_commands.py | 21 ++++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/adapter/telegram/handlers/commands.py b/adapter/telegram/handlers/commands.py index d56b0bb..7f2e628 100644 --- a/adapter/telegram/handlers/commands.py +++ b/adapter/telegram/handlers/commands.py @@ -50,10 +50,20 @@ async def cmd_archive(message: Message) -> None: await message.answer("Этот чат не найден или уже архивирован.") return db.archive_chat(user_id=user_id, thread_id=thread_id) - await message.answer( - "Чат архивирован — бот больше не будет отвечать здесь.\n\n" - "Чтобы удалить топик из списка: удержи его в списке чатов → «Удалить тему»." - ) + + try: + await message.bot.delete_forum_topic( + chat_id=message.chat.id, message_thread_id=thread_id + ) + logger.info("cmd_archive_deleted", user_id=user_id, thread_id=thread_id) + except TelegramBadRequest as e: + logger.warning("cmd_archive_delete_failed", error=str(e)) + await message.answer( + "Чат архивирован — бот больше не будет отвечать здесь.\n\n" + "Удалить топик из списка не получится: он создан ботом, " + "а Telegram не позволяет пользователям удалять чужие топики." + ) + logger.info("cmd_archive", user_id=user_id, thread_id=thread_id) diff --git a/tests/adapter/telegram/test_commands.py b/tests/adapter/telegram/test_commands.py index ff849df..a9b6676 100644 --- a/tests/adapter/telegram/test_commands.py +++ b/tests/adapter/telegram/test_commands.py @@ -30,6 +30,7 @@ def make_message(*, user_id=1, thread_id=42, chat_id=100, text="/new"): return_value=SimpleNamespace(message_thread_id=200) ) m.bot.close_forum_topic = AsyncMock() + m.bot.delete_forum_topic = AsyncMock() m.bot.edit_forum_topic = AsyncMock() m.bot.send_message = AsyncMock() return m @@ -47,14 +48,28 @@ async def test_cmd_new_creates_topic(fresh_db, monkeypatch): assert fresh_db.get_chat(1, 200) is not None -async def test_cmd_archive_closes_and_archives(fresh_db, monkeypatch): +async def test_cmd_archive_deletes_topic_when_possible(fresh_db, monkeypatch): + """When delete_forum_topic succeeds (user-created topic), no answer is sent.""" import adapter.telegram.handlers.commands as mod importlib.reload(mod) fresh_db.create_chat(1, 42, "Чат #1") msg = make_message(user_id=1, thread_id=42, chat_id=100) await mod.cmd_archive(msg) - # close_forum_topic is NOT called — unsupported in Threaded Mode personal chats - msg.bot.close_forum_topic.assert_not_called() + msg.bot.delete_forum_topic.assert_called_once_with(chat_id=100, message_thread_id=42) + assert fresh_db.get_chat(1, 42)["archived_at"] is not None + msg.answer.assert_not_called() + + +async def test_cmd_archive_fallback_message_when_delete_fails(fresh_db, monkeypatch): + """When delete_forum_topic fails (bot-created topic), user gets explanation.""" + import adapter.telegram.handlers.commands as mod + importlib.reload(mod) + fresh_db.create_chat(1, 42, "Чат #1") + msg = make_message(user_id=1, thread_id=42, chat_id=100) + msg.bot.delete_forum_topic = AsyncMock( + side_effect=TelegramBadRequest(method=MagicMock(), message="not a supergroup forum") + ) + await mod.cmd_archive(msg) assert fresh_db.get_chat(1, 42)["archived_at"] is not None msg.answer.assert_called_once() assert "архивирован" in msg.answer.call_args[0][0]