From 84adcce57b3d31ccda9eff957a31c080cba1f732 Mon Sep 17 00:00:00 2001 From: "Andrew K. Choi" Date: Mon, 17 Nov 2025 11:54:15 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BC=D0=B0=D1=81=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B5=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20broadcast=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D1=83=20=D0=B2=D1=81=D0=B5=D1=85=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Quick delete теперь удаляет сообщения у всех получателей broadcast - Добавлен метод get_message_by_telegram_id в ChatMessageService - При удалении проходит по всем forwarded_message_ids и удаляет у каждого - Показывает статистику удаления админу (автоматически исчезает через 3 сек) - Помечает сообщение как удалённое в БД --- .bot.pid | 2 +- src/core/chat_services.py | 17 +++++++ src/handlers/message_management.py | 73 +++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/.bot.pid b/.bot.pid index 79b6477..df91274 100644 --- a/.bot.pid +++ b/.bot.pid @@ -1 +1 @@ -1011501 +1014690 diff --git a/src/core/chat_services.py b/src/core/chat_services.py index 8755fa3..c8a74ee 100644 --- a/src/core/chat_services.py +++ b/src/core/chat_services.py @@ -185,6 +185,23 @@ class ChatMessageService: ) return result.scalar_one_or_none() + @staticmethod + async def get_message_by_telegram_id( + session: AsyncSession, + telegram_message_id: int, + user_id: Optional[int] = None + ) -> Optional[ChatMessage]: + """Получить сообщение по telegram_message_id""" + query = select(ChatMessage).where( + ChatMessage.telegram_message_id == telegram_message_id + ) + + if user_id: + query = query.where(ChatMessage.user_id == user_id) + + result = await session.execute(query) + return result.scalar_one_or_none() + @staticmethod async def get_user_messages( session: AsyncSession, diff --git a/src/handlers/message_management.py b/src/handlers/message_management.py index 2764a63..219ab77 100644 --- a/src/handlers/message_management.py +++ b/src/handlers/message_management.py @@ -2,11 +2,13 @@ Хэндлеры для управления сообщениями администратором """ import logging -from aiogram import Router, F +from aiogram import Router, F, Bot from aiogram.types import Message, CallbackQuery from aiogram.filters import Command from ..core.config import ADMIN_IDS +from ..core.database import async_session_maker +from ..core.chat_services import ChatMessageService logger = logging.getLogger(__name__) @@ -86,16 +88,75 @@ async def quick_delete_replied_message(message: Message): - "удалить", "delete", "del" - 🗑️ (мусорная корзина) - ❌ (крестик) + + Удаляет сообщение у всех получателей broadcast рассылки """ if not is_admin(message.from_user.id): return # Не админ - пропускаем try: - # Удаляем сообщение на которое ответили - await message.reply_to_message.delete() - # Удаляем команду + replied_msg = message.reply_to_message + deleted_count = 0 + + # Пытаемся найти сообщение в БД по telegram_message_id + async with async_session_maker() as session: + chat_message = await ChatMessageService.get_message_by_telegram_id( + session, + telegram_message_id=replied_msg.message_id + ) + + # Если нашли broadcast сообщение - удаляем у всех получателей + if chat_message and chat_message.forwarded_message_ids: + bot = message.bot + + for user_telegram_id, forwarded_msg_id in chat_message.forwarded_message_ids.items(): + try: + await bot.delete_message( + chat_id=int(user_telegram_id), + message_id=forwarded_msg_id + ) + deleted_count += 1 + except Exception as e: + logger.warning(f"Не удалось удалить сообщение у {user_telegram_id}: {e}") + + # Помечаем как удалённое в БД + await ChatMessageService.delete_message( + session, + message_id=chat_message.id, + deleted_by=message.from_user.id + ) + + logger.info( + f"Администратор {message.from_user.id} удалил broadcast сообщение " + f"{replied_msg.message_id} у {deleted_count} получателей" + ) + + # Удаляем исходное сообщение (на которое ответили) + await replied_msg.delete() + + # Удаляем команду админа await message.delete() - logger.info(f"Администратор {message.from_user.id} быстро удалил сообщение {message.reply_to_message.message_id}") + + # Если было broadcast удаление - показываем статистику + if deleted_count > 0: + status_msg = await message.answer( + f"✅ Сообщение удалено у {deleted_count} получателей", + reply_to_message_id=None + ) + # Удаляем статус через 3 секунды + import asyncio + await asyncio.sleep(3) + try: + await status_msg.delete() + except: + pass + except Exception as e: logger.error(f"Ошибка при быстром удалении сообщения: {e}") - await message.answer(f"❌ Не удалось удалить: {str(e)}", reply_to_message_id=message.message_id) + try: + await message.answer( + f"❌ Не удалось удалить: {str(e)}", + reply_to_message_id=message.message_id + ) + except: + pass