""" Хэндлеры для управления сообщениями администратором """ import logging from aiogram import Router, F, Bot from aiogram.types import Message, CallbackQuery from aiogram.filters import Command from src.filters.case_insensitive import CaseInsensitiveCommand from ..core.config import ADMIN_IDS from ..core.database import async_session_maker from ..core.chat_services import ChatMessageService from ..core.services import UserService logger = logging.getLogger(__name__) message_admin_router = Router(name="message_admin") def is_admin(user_id: int) -> bool: """Проверка, является ли пользователь администратором""" return user_id in ADMIN_IDS @message_admin_router.message(CaseInsensitiveCommand("delete")) async def delete_replied_message(message: Message): """ Удаление сообщения по команде /delete (регистронезависимо) Работает только если команда является ответом на сообщение бота """ if not is_admin(message.from_user.id): await message.answer("❌ Недостаточно прав") return if not message.reply_to_message: await message.answer("⚠️ Ответьте на сообщение бота командой /delete чтобы удалить его") return if message.reply_to_message.from_user.id != message.bot.id: await message.answer("⚠️ Можно удалять только сообщения бота") return try: # Удаляем сообщение бота await message.reply_to_message.delete() # Удаляем команду await message.delete() logger.info(f"Администратор {message.from_user.id} удалил сообщение {message.reply_to_message.message_id}") except Exception as e: logger.error(f"Ошибка при удалении сообщения: {e}") await message.answer(f"❌ Не удалось удалить сообщение: {str(e)}") @message_admin_router.callback_query(F.data == "delete_message") async def delete_message_callback(callback: CallbackQuery): """ Удаление сообщения по нажатию кнопки """ if not is_admin(callback.from_user.id): await callback.answer("❌ Недостаточно прав", show_alert=True) return try: await callback.message.delete() await callback.answer("✅ Сообщение удалено") logger.info(f"Администратор {callback.from_user.id} удалил сообщение через кнопку") except Exception as e: logger.error(f"Ошибка при удалении сообщения через кнопку: {e}") await callback.answer(f"❌ Ошибка: {str(e)}", show_alert=True) # Функция-фильтр для проверки триггерных слов def is_delete_trigger(message: Message) -> bool: """Проверяет, является ли сообщение триггером для удаления""" if not message.text: return False text_lower = message.text.lower().strip() triggers = ["удалить", "delete", "del", "🗑️", "🗑", "❌"] return any(trigger in text_lower for trigger in triggers) @message_admin_router.message(F.reply_to_message, is_delete_trigger) async def quick_delete_replied_message(message: Message): """ Быстрое удаление сообщения по reply с триггерными словами или emoji Работает для админов при ответе на любое сообщение Триггеры: - "удалить", "delete", "del" - 🗑️ (мусорная корзина) - ❌ (крестик) Удаляет сообщение у всех получателей broadcast рассылки """ if not is_admin(message.from_user.id): return # Не админ - пропускаем try: replied_msg = message.reply_to_message deleted_count = 0 # Пытаемся найти сообщение в БД по telegram_message_id async with async_session_maker() as session: # Получаем admin user для deleted_by admin_user = await UserService.get_user_by_telegram_id( session, message.from_user.id ) if not admin_user: logger.error(f"Админ {message.from_user.id} не найден в БД") await message.answer("❌ Ошибка: пользователь не найден") return 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}") # Помечаем как удалённое в БД (используем admin_user.id, а не telegram_id) await ChatMessageService.delete_message( session, message_id=chat_message.id, deleted_by=admin_user.id ) logger.info( f"Администратор {message.from_user.id} удалил broadcast сообщение " f"{replied_msg.message_id} у {deleted_count} получателей" ) # Удаляем исходное сообщение (на которое ответили) try: await replied_msg.delete() except Exception as e: logger.warning(f"Не удалось удалить исходное сообщение: {e}") # Удаляем команду админа try: await message.delete() except Exception as e: logger.warning(f"Не удалось удалить команду админа: {e}") # Если было broadcast удаление - показываем статистику if deleted_count > 0: try: status_msg = await message.answer( f"✅ Сообщение удалено у {deleted_count} получателей", reply_to_message_id=None ) # Удаляем статус через 3 секунды import asyncio await asyncio.sleep(3) await status_msg.delete() except Exception as e: logger.warning(f"Не удалось показать/удалить статус: {e}") except Exception as e: logger.error(f"Ошибка при быстром удалении сообщения: {e}") try: # Пытаемся удалить хотя бы команду админа await message.delete() except: pass