diff --git a/bot/handlers/commands/users/notifications.py b/bot/handlers/commands/users/notifications.py new file mode 100644 index 0000000..beff962 --- /dev/null +++ b/bot/handlers/commands/users/notifications.py @@ -0,0 +1,118 @@ +""" +Обработчики callback-кнопок уведомлений о спаме +""" +from aiogram import Router, F +from aiogram.types import CallbackQuery +from aiogram.exceptions import TelegramBadRequest + +from bot.filters.admin import IsAdmin +from database import get_manager +from middleware.loggers import logger + +__all__ = ("router",) + +router: Router = Router(name="spam_notifications_router") + + +# ================= ЗАКРЫТИЕ УВЕДОМЛЕНИЯ ================= + +@router.callback_query(F.data == "spam_close", IsAdmin()) +async def spam_close_callback(callback: CallbackQuery) -> None: + """ + Закрывает (удаляет) уведомление о спаме. + """ + try: + await callback.message.delete() + await callback.answer("✅ Уведомление закрыто") + + logger.debug( + f"Уведомление о спаме закрыто админом {callback.from_user.id}", + log_type="SPAM_NOTIFICATION" + ) + + except TelegramBadRequest as e: + logger.error(f"Ошибка удаления уведомления: {e}", log_type="ERROR") + await callback.answer("❌ Не удалось удалить уведомление", show_alert=True) + + +# ================= БАН ПОЛЬЗОВАТЕЛЯ ================= + +@router.callback_query(F.data.startswith("spam_ban:"), IsAdmin()) +async def spam_ban_callback(callback: CallbackQuery) -> None: + """ + Банит пользователя прямо из уведомления. + """ + try: + # Парсим данные: spam_ban:user_id:chat_id + parts = callback.data.split(":") + user_id = int(parts[1]) + chat_id = int(parts[2]) + + # Баним пользователя + try: + await callback.bot.ban_chat_member( + chat_id=chat_id, + user_id=user_id + ) + + # Обновляем сообщение + updated_text = callback.message.text + f"\n\n🔨 Пользователь забанен (@{callback.from_user.username or callback.from_user.id})" + + # Убираем кнопки + await callback.message.edit_text( + text=updated_text, + parse_mode="HTML" + ) + + await callback.answer("✅ Пользователь забанен", show_alert=True) + + logger.info( + f"Пользователь {user_id} забанен админом {callback.from_user.id} через уведомление о спаме", + log_type="SPAM_BAN" + ) + + except TelegramBadRequest as e: + await callback.answer(f"❌ Ошибка бана: {str(e)}", show_alert=True) + + except Exception as e: + logger.error(f"Ошибка обработки бана из уведомления: {e}", log_type="ERROR") + await callback.answer("❌ Ошибка выполнения", show_alert=True) + + +# ================= СТАТИСТИКА ПОЛЬЗОВАТЕЛЯ ================= + +@router.callback_query(F.data.startswith("spam_stats:"), IsAdmin()) +async def spam_stats_callback(callback: CallbackQuery) -> None: + """ + Показывает статистику пользователя. + """ + try: + # Парсим данные: spam_stats:user_id + parts = callback.data.split(":") + user_id = int(parts[1]) + + manager = get_manager() + + # Получаем статистику + spam_count = await manager.get_user_spam_count(user_id) + recent_spam = await manager.get_spam_stats(limit=5, user_id=user_id) + + # Формируем текст + text = f"📊 Статистика пользователя\n\n" + text += f"🆔 ID: {user_id}\n" + text += f"🗑 Удалено сообщений: {spam_count}\n\n" + + if recent_spam: + text += f"📝 Последние нарушения:\n" + for idx, stat in enumerate(recent_spam, 1): + matched_word = stat.matched_word or "неизвестно" + match_type = stat.match_type or "unknown" + text += f"{idx}. {matched_word} ({match_type})\n" + else: + text += "✅ Нет нарушений" + + await callback.answer(text, show_alert=True) + + except Exception as e: + logger.error(f"Ошибка получения статистики из уведомления: {e}", log_type="ERROR") + await callback.answer("❌ Ошибка получения статистики", show_alert=True)