From 4d1eb3e2317e1dbe38dd12022d2e7297bbe8a03a Mon Sep 17 00:00:00 2001 From: Verum Date: Mon, 23 Feb 2026 14:38:37 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D1=8C=D1=82=D1=80=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=B8=D0=B2=D0=BD=D1=8B=D1=85=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B0=D0=BD=D1=82=D0=B8-=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=84=D0=BB=D0=B8=D0=BA=D1=82=20=D0=B8=20"=D0=BC=D0=BE=D0=BB?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=BA=D0=B8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot/filters/modes.py | 184 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 bot/filters/modes.py diff --git a/bot/filters/modes.py b/bot/filters/modes.py new file mode 100644 index 0000000..fbc3248 --- /dev/null +++ b/bot/filters/modes.py @@ -0,0 +1,184 @@ +""" +Фильтры для проверки активных режимов бота (silence, conflict) +""" +from datetime import datetime +from typing import Optional + +from aiogram.filters import BaseFilter +from aiogram.types import Message + +from middleware.loggers import logger + +__all__ = ('IsSilenceActive', 'IsConflictModeActive') + + +class IsSilenceActive(BaseFilter): + """ + Проверяет, активен ли режим тишины (silence mode). + + В режиме тишины удаляются ВСЕ сообщения (кроме админов). + + Attributes: + silence_until: Время до которого активен режим (None = неактивен) + + Example: + ```python + # В handler-файле + silence_filter = IsSilenceActive() + + @router.message(silence_filter) + async def silence_mode_active(message: Message): + # Удаляем все сообщения в режиме тишины + await message.delete() + ``` + """ + + def __init__(self, silence_until: Optional[datetime] = None): + """ + Args: + silence_until: Datetime до которого активен режим + """ + self.silence_until = silence_until + + def update_silence_until(self, new_datetime: Optional[datetime]) -> None: + """ + Обновляет время окончания режима тишины. + + Args: + new_datetime: Новое время окончания или None для отключения + """ + self.silence_until = new_datetime + + if new_datetime: + logger.info( + f"Режим тишины активирован до {new_datetime.strftime('%H:%M:%S')}", + log_type='SILENCE' + ) + else: + logger.info("Режим тишины отключен", log_type='SILENCE') + + def is_active(self) -> bool: + """ + Проверяет, активен ли режим сейчас. + + Returns: + bool: True если режим активен + """ + if self.silence_until is None: + return False + + # Проверка истечения времени + if datetime.now() >= self.silence_until: + logger.info("Режим тишины автоматически завершен", log_type='SILENCE') + self.silence_until = None + return False + + return True + + async def __call__(self, event: Message) -> Optional[dict]: + """ + Проверка активности режима тишины. + + Returns: + dict или None: Информация о режиме если активен, иначе None + """ + if self.is_active(): + remaining = (self.silence_until - datetime.now()).total_seconds() + logger.debug( + f"Режим тишины активен (осталось {remaining:.0f}с)", + log_type='SILENCE', + message=event + ) + return { + 'is_active': True, + 'until': self.silence_until, + 'remaining_seconds': remaining + } + + return None + + +class IsConflictModeActive(BaseFilter): + """ + Проверяет, активен ли режим антиконфликта (conflict mode). + + В режиме антиконфликта удаляются сообщения с конфликтными словами. + + Attributes: + conflict_until: Время до которого активен режим (None = неактивен) + + Example: + ```python + conflict_filter = IsConflictModeActive() + + @router.message(conflict_filter) + async def conflict_mode_active(message: Message): + # Проверяем на конфликтные слова и удаляем + if has_conflict_words(message.text): + await message.delete() + ``` + """ + + def __init__(self, conflict_until: Optional[datetime] = None): + """ + Args: + conflict_until: Datetime до которого активен режим + """ + self.conflict_until = conflict_until + + def update_conflict_until(self, new_datetime: Optional[datetime]) -> None: + """ + Обновляет время окончания режима антиконфликта. + + Args: + new_datetime: Новое время окончания или None для отключения + """ + self.conflict_until = new_datetime + + if new_datetime: + logger.info( + f"Режим антиконфликта активирован до {new_datetime.strftime('%H:%M:%S')}", + log_type='CONFLICT' + ) + else: + logger.info("Режим антиконфликта отключен", log_type='CONFLICT') + + def is_active(self) -> bool: + """ + Проверяет, активен ли режим сейчас. + + Returns: + bool: True если режим активен + """ + if self.conflict_until is None: + return False + + # Проверка истечения времени + if datetime.now() >= self.conflict_until: + logger.info("Режим антиконфликта автоматически завершен", log_type='CONFLICT') + self.conflict_until = None + return False + + return True + + async def __call__(self, event: Message) -> Optional[dict]: + """ + Проверка активности режима антиконфликта. + + Returns: + dict или None: Информация о режиме если активен, иначе None + """ + if self.is_active(): + remaining = (self.conflict_until - datetime.now()).total_seconds() + logger.debug( + f"Режим антиконфликта активен (осталось {remaining:.0f}с)", + log_type='CONFLICT', + message=event + ) + return { + 'is_active': True, + 'until': self.conflict_until, + 'remaining_seconds': remaining + } + + return None