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)