diff --git a/bot/handlers/commands/users/conflict.py b/bot/handlers/commands/users/conflict.py
new file mode 100644
index 0000000..8e75b95
--- /dev/null
+++ b/bot/handlers/commands/users/conflict.py
@@ -0,0 +1,435 @@
+"""
+Обработчики команд режима антиконфликта
+"""
+from datetime import datetime
+from aiogram import Router
+from aiogram.filters import Command
+from aiogram.types import Message
+
+from bot.filters.admin import IsAdmin
+from configs import settings, COMMANDS
+from database import get_manager
+from database.models import BanWordType
+from middleware.loggers import logger
+from bot.utils.decorators import log_action
+
+__all__ = ("router",)
+
+router: Router = Router(name="conflict_mode_router")
+
+
+# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ =================
+
+def parse_conflict_args(text: str, command: str, need_minutes: bool = False) -> tuple[bool, str | list]:
+ """
+ Парсит аргументы команды для конфликтного режима.
+
+ Args:
+ text: Полный текст сообщения
+ command: Название команды
+ need_minutes: Требуется ли параметр минут
+
+ Returns:
+ (success, result): result это либо список аргументов, либо текст ошибки
+ """
+ parts = text.split(maxsplit=2 if need_minutes else 1)
+
+ min_args = 1 if need_minutes else 1
+
+ if len(parts) < min_args + 1:
+ if need_minutes:
+ return False, f"❌ Использование: /{command} [минуты]"
+ else:
+ return False, f"❌ Использование: /{command} [слово]"
+
+ args = parts[1:]
+
+ # Валидация слова
+ if not need_minutes:
+ if len(args[0]) < 2:
+ return False, "❌ Слово должно содержать минимум 2 символа"
+
+ if len(args[0]) > 100:
+ return False, "❌ Слово слишком длинное (максимум 100 символов)"
+
+ return True, args
+
+
+def format_time_str(minutes: int) -> str:
+ """Форматирует время в читабельный формат"""
+ if minutes < 60:
+ return f"{minutes} мин"
+ elif minutes < 1440:
+ hours = minutes // 60
+ mins = minutes % 60
+ return f"{hours}ч {mins}м" if mins else f"{hours}ч"
+ else:
+ days = minutes // 1440
+ hours = (minutes % 1440) // 60
+ return f"{days}д {hours}ч" if hours else f"{days}д"
+
+
+def format_datetime(dt: datetime) -> str:
+ """Форматирует datetime в читабельный формат"""
+ return dt.strftime("%d.%m.%Y %H:%M:%S")
+
+
+# ================= ДОБАВЛЕНИЕ КОНФЛИКТНЫХ СЛОВ =================
+
+@router.message(
+ Command(*COMMANDS.get("addconflictword", ["addconflictword"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin())
+@log_action(action_name="ADD_CONFLICT_WORD", log_args=True)
+async def add_conflict_word_cmd(message: Message) -> None:
+ """
+ Добавляет конфликтное слово-подстроку.
+
+ Конфликтные слова работают только в режиме /stopconflict.
+
+ Использование: /addconflictword <слово>
+ """
+ success, result = parse_conflict_args(message.text, "addconflictword", need_minutes=False)
+
+ if not success:
+ await message.answer(result, parse_mode="HTML")
+ return
+
+ word = result[0].lower().strip()
+ manager = get_manager()
+
+ try:
+ added = await manager.add_banword(
+ word=word,
+ word_type=BanWordType.CONFLICT_SUBSTRING,
+ added_by=message.from_user.id,
+ reason="Конфликтное слово"
+ )
+
+ if added:
+ text = (
+ f"✅ Конфликтное слово добавлено\n\n"
+ f"📝 Слово: {word}\n"
+ f"🔍 Тип: подстрока\n\n"
+ f"⚔️ Будет работать только в режиме антиконфликта\n"
+ f"Активируйте: /stopconflict [минуты]"
+ )
+ else:
+ text = f"⚠️ Конфликтное слово {word} уже существует"
+
+ await message.answer(text, parse_mode="HTML")
+
+ except Exception as e:
+ logger.error(f"Ошибка добавления конфликтного слова: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML")
+
+
+@router.message(
+ Command(*COMMANDS.get("addconflictlemma", ["addconflictlemma"]), prefix=settings.PREFIX, ignore_case=True),
+ IsAdmin())
+@log_action(action_name="ADD_CONFLICT_LEMMA", log_args=True)
+async def add_conflict_lemma_cmd(message: Message) -> None:
+ """
+ Добавляет конфликтную лемму.
+
+ Конфликтные леммы работают только в режиме /stopconflict.
+
+ Использование: /addconflictlemma <слово>
+ """
+ success, result = parse_conflict_args(message.text, "addconflictlemma", need_minutes=False)
+
+ if not success:
+ await message.answer(result, parse_mode="HTML")
+ return
+
+ word = result[0].lower().strip()
+ manager = get_manager()
+
+ try:
+ added = await manager.add_banword(
+ word=word,
+ word_type=BanWordType.CONFLICT_LEMMA,
+ added_by=message.from_user.id,
+ reason="Конфликтная лемма"
+ )
+
+ if added:
+ text = (
+ f"✅ Конфликтная лемма добавлена\n\n"
+ f"🔤 Слово: {word}\n"
+ f"🔍 Тип: лемма (все формы слова)\n\n"
+ f"⚔️ Будет работать только в режиме антиконфликта\n"
+ f"Активируйте: /stopconflict [минуты]"
+ )
+ else:
+ text = f"⚠️ Конфликтная лемма {word} уже существует"
+
+ await message.answer(text, parse_mode="HTML")
+
+ except Exception as e:
+ logger.error(f"Ошибка добавления конфликтной леммы: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML")
+
+
+# ================= УДАЛЕНИЕ КОНФЛИКТНЫХ СЛОВ =================
+
+@router.message(
+ Command(*COMMANDS.get("remconflictword", ["remconflictword"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin())
+@log_action(action_name="REMOVE_CONFLICT_WORD", log_args=True)
+async def remove_conflict_word_cmd(message: Message) -> None:
+ """
+ Удаляет конфликтное слово-подстроку.
+
+ Использование: /remconflictword <слово>
+ """
+ success, result = parse_conflict_args(message.text, "remconflictword", need_minutes=False)
+
+ if not success:
+ await message.answer(result, parse_mode="HTML")
+ return
+
+ word = result[0].lower().strip()
+ manager = get_manager()
+
+ try:
+ removed = await manager.remove_banword(
+ word=word,
+ word_type=BanWordType.CONFLICT_SUBSTRING
+ )
+
+ if removed:
+ text = f"🗑 Конфликтное слово удалено\n\n📝 Слово: {word}"
+ else:
+ text = f"⚠️ Конфликтное слово {word} не найдено"
+
+ await message.answer(text, parse_mode="HTML")
+
+ except Exception as e:
+ logger.error(f"Ошибка удаления конфликтного слова: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML")
+
+
+@router.message(
+ Command(*COMMANDS.get("remconflictlemma", ["remconflictlemma"]), prefix=settings.PREFIX, ignore_case=True),
+ IsAdmin())
+@log_action(action_name="REMOVE_CONFLICT_LEMMA", log_args=True)
+async def remove_conflict_lemma_cmd(message: Message) -> None:
+ """
+ Удаляет конфликтную лемму.
+
+ Использование: /remconflictlemma <слово>
+ """
+ success, result = parse_conflict_args(message.text, "remconflictlemma", need_minutes=False)
+
+ if not success:
+ await message.answer(result, parse_mode="HTML")
+ return
+
+ word = result[0].lower().strip()
+ manager = get_manager()
+
+ try:
+ removed = await manager.remove_banword(
+ word=word,
+ word_type=BanWordType.CONFLICT_LEMMA
+ )
+
+ if removed:
+ text = f"🗑 Конфликтная лемма удалена\n\n🔤 Слово: {word}"
+ else:
+ text = f"⚠️ Конфликтная лемма {word} не найдена"
+
+ await message.answer(text, parse_mode="HTML")
+
+ except Exception as e:
+ logger.error(f"Ошибка удаления конфликтной леммы: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML")
+
+
+# ================= УПРАВЛЕНИЕ РЕЖИМОМ АНТИКОНФЛИКТА =================
+
+@router.message(Command(*COMMANDS.get("stopconflict", ["stopconflict"]), prefix=settings.PREFIX, ignore_case=True),
+ IsAdmin())
+@log_action(action_name="START_CONFLICT_MODE", log_args=True)
+async def start_conflict_mode_cmd(message: Message) -> None:
+ """
+ Активирует режим антиконфликта на указанное время.
+
+ В этом режиме работают только конфликтные слова/леммы.
+ Обычные банворды временно отключаются.
+
+ Использование: /stopconflict <минуты>
+ Пример: /stopconflict 30
+ """
+ success, result = parse_conflict_args(message.text, "stopconflict", need_minutes=True)
+
+ if not success:
+ await message.answer(result, parse_mode="HTML")
+ return
+
+ # Валидация минут
+ try:
+ minutes = int(result[0])
+ if minutes < 1 or minutes > 10080: # Максимум неделя
+ await message.answer(
+ "❌ Время должно быть от 1 минуты до 10080 минут (7 дней)",
+ parse_mode="HTML"
+ )
+ return
+ except ValueError:
+ await message.answer("❌ Неверный формат времени. Укажите число минут", parse_mode="HTML")
+ return
+
+ manager = get_manager()
+
+ try:
+ # Получаем статистику конфликтных слов
+ data = await manager.get_all_words_list()
+ conflict_words_count = len(data.get('conflict_substring', set()))
+ conflict_lemmas_count = len(data.get('conflict_lemma', set()))
+ total_conflict = conflict_words_count + conflict_lemmas_count
+
+ if total_conflict == 0:
+ await message.answer(
+ "⚠️ Нет конфликтных слов\n\n"
+ "Сначала добавьте конфликтные слова:\n"
+ "• /addconflictword [слово]\n"
+ "• /addconflictlemma [слово]",
+ parse_mode="HTML"
+ )
+ return
+
+ # Активируем режим
+ expires_at = await manager.set_conflict_mode(minutes)
+
+ time_str = format_time_str(minutes)
+ expires_str = format_datetime(expires_at)
+
+ text = (
+ f"⚔️ РЕЖИМ АНТИКОНФЛИКТА АКТИВИРОВАН\n\n"
+ f"⏱ Длительность: {time_str}\n"
+ f"🕐 Окончание: {expires_str}\n\n"
+ f"📊 Активные правила:\n"
+ f"├─ Конфликтные слова: {conflict_words_count}\n"
+ f"└─ Конфликтные леммы: {conflict_lemmas_count}\n\n"
+ f"⚠️ Обычные банворды временно отключены\n"
+ f"Отключить режим: /unstopconflict"
+ )
+
+ await message.answer(text, parse_mode="HTML")
+
+ logger.info(
+ f"Режим антиконфликта активирован на {minutes} мин "
+ f"(конфликтных правил: {total_conflict})",
+ log_type="CONFLICT"
+ )
+
+ except Exception as e:
+ logger.error(f"Ошибка активации режима антиконфликта: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка активации режима\n\nПопробуйте позже", parse_mode="HTML")
+
+
+@router.message(Command(*COMMANDS.get("unstopconflict", ["unstopconflict"]), prefix=settings.PREFIX, ignore_case=True),
+ IsAdmin())
+@log_action(action_name="STOP_CONFLICT_MODE")
+async def stop_conflict_mode_cmd(message: Message) -> None:
+ """
+ Отключает режим антиконфликта.
+
+ Использование: /unstopconflict
+ """
+ manager = get_manager()
+
+ try:
+ # Проверяем, активен ли режим
+ is_active = await manager.is_conflict_active()
+
+ if not is_active:
+ await message.answer(
+ "⚠️ Режим антиконфликта не активен\n\n"
+ "Активируйте: /stopconflict [минуты]",
+ parse_mode="HTML"
+ )
+ return
+
+ # Отключаем режим
+ await manager.disable_conflict_mode()
+
+ text = (
+ f"✅ Режим антиконфликта отключен\n\n"
+ f"🔄 Обычные банворды снова активны\n"
+ f"⚔️ Конфликтные слова деактивированы"
+ )
+
+ await message.answer(text, parse_mode="HTML")
+
+ logger.info("Режим антиконфликта отключён", log_type="CONFLICT")
+
+ except Exception as e:
+ logger.error(f"Ошибка отключения режима антиконфликта: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка отключения режима\n\nПопробуйте позже", parse_mode="HTML")
+
+
+@router.message(Command(*COMMANDS.get("conflictstatus", ["conflictstatus"]), prefix=settings.PREFIX, ignore_case=True),
+ IsAdmin())
+@log_action(action_name="CONFLICT_STATUS")
+async def conflict_status_cmd(message: Message) -> None:
+ """
+ Показывает статус режима антиконфликта.
+
+ Использование: /conflictstatus
+ """
+ manager = get_manager()
+
+ try:
+ # Проверяем активность режима
+ is_active = await manager.is_conflict_active()
+
+ # Получаем статистику
+ data = await manager.get_all_words_list()
+ conflict_words_count = len(data.get('conflict_substring', set()))
+ conflict_lemmas_count = len(data.get('conflict_lemma', set()))
+ total_conflict = conflict_words_count + conflict_lemmas_count
+
+ if is_active:
+ # Режим активен - показываем детали
+ conflict_until_str = await manager.repo.get_setting("conflict_until")
+ conflict_until = float(conflict_until_str)
+ expires_at = datetime.fromtimestamp(conflict_until)
+
+ now = datetime.now()
+ time_left_seconds = (expires_at - now).total_seconds()
+ time_left_minutes = int(time_left_seconds / 60)
+
+ text = (
+ f"⚔️ РЕЖИМ АНТИКОНФЛИКТА АКТИВЕН\n\n"
+ f"⏱ Осталось: {format_time_str(time_left_minutes)}\n"
+ f"🕐 Окончание: {format_datetime(expires_at)}\n\n"
+ f"📊 Активные правила:\n"
+ f"├─ Конфликтные слова: {conflict_words_count}\n"
+ f"└─ Конфликтные леммы: {conflict_lemmas_count}\n\n"
+ f"⚠️ Обычные банворды отключены\n"
+ f"Отключить: /unstopconflict"
+ )
+ else:
+ # Режим не активен
+ text = (
+ f"💤 Режим антиконфликта НЕ активен\n\n"
+ f"📊 Конфликтных правил в базе:\n"
+ f"├─ Слова: {conflict_words_count}\n"
+ f"└─ Леммы: {conflict_lemmas_count}\n\n"
+ )
+
+ if total_conflict > 0:
+ text += f"Активировать: /stopconflict [минуты]"
+ else:
+ text += (
+ f"⚠️ Нет конфликтных слов\n"
+ f"Добавьте:\n"
+ f"• /addconflictword [слово]\n"
+ f"• /addconflictlemma [слово]"
+ )
+
+ await message.answer(text, parse_mode="HTML")
+
+ except Exception as e:
+ logger.error(f"Ошибка получения статуса режима: {e}", log_type="CONFLICT")
+ await message.answer("❌ Ошибка получения статуса", parse_mode="HTML")