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