From a06448ca4b3e9314551f71df3098b043ba4c52a4 Mon Sep 17 00:00:00 2001 From: Whyverum Date: Tue, 17 Feb 2026 11:24:55 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D1=8B=D0=B9=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 52 ++ .env_example | 253 ++++++ .gitattributes | 97 +++ .gitignore | 71 ++ .idea/.gitignore | 8 + .idea/PrimoGuardBot.iml | 29 + .idea/inspectionProfiles/Project_Default.xml | 6 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + Dockerfile | 17 + LICENSE | 21 + README.md | Bin 0 -> 26688 bytes assets/photo/default.jpg | Bin 0 -> 567481 bytes assets/photo/start.jpg | Bin 0 -> 440660 bytes bot/__init__.py | 4 + bot/core/__init__.py | 5 + bot/core/bots.py | 398 +++++++++ bot/core/webhook.py | 259 ++++++ bot/filters/__init__.py | 11 + bot/filters/admin.py | 109 +++ bot/filters/callback.py | 253 ++++++ bot/filters/chat_rights.py | 324 +++++++ bot/filters/chat_type.py | 105 +++ bot/filters/modes.py | 184 ++++ bot/filters/msg_content.py | 395 +++++++++ bot/filters/spam.py | 111 +++ bot/filters/subscription.py | 246 ++++++ bot/handlers/__init__.py | 14 + bot/handlers/commands/__init__.py | 16 + bot/handlers/commands/admins/__init__.py | 18 + bot/handlers/commands/admins/all_cmd.py | 81 ++ bot/handlers/commands/admins/ban_cmd.py | 258 ++++++ bot/handlers/commands/admins/kick_cmd.py | 277 ++++++ bot/handlers/commands/admins/pin_cmd.py | 77 ++ bot/handlers/commands/admins/settings_cmd.py | 51 ++ bot/handlers/commands/settings/__init__.py | 19 + .../commands/settings/set_description_cmd.py | 173 ++++ .../commands/settings/set_name_cmd.py | 157 ++++ .../commands/settings/set_widget_cmd.py | 174 ++++ .../commands/settings/settings_cmd.py | 48 + bot/handlers/commands/users/__init__.py | 33 + bot/handlers/commands/users/admins.py | 434 ++++++++++ bot/handlers/commands/users/conflict.py | 435 ++++++++++ bot/handlers/commands/users/emoji.py | 215 +++++ bot/handlers/commands/users/id.py | 221 +++++ bot/handlers/commands/users/listwords.py | 238 +++++ bot/handlers/commands/users/notifications.py | 118 +++ bot/handlers/commands/users/report.py | 447 ++++++++++ bot/handlers/commands/users/slience.py | 346 ++++++++ bot/handlers/commands/users/start_cmd.py | 168 ++++ bot/handlers/commands/users/stats.py | 589 +++++++++++++ bot/handlers/commands/users/word.py | 546 ++++++++++++ bot/handlers/messages/__init__.py | 15 + bot/handlers/messages/default_msg.py | 11 + bot/handlers/messages/ping_test.py | 32 + bot/keyboards/__init__.py | 2 + bot/keyboards/inline.py | 17 + bot/keyboards/inline/__init__.py | 1 + bot/keyboards/inline/decision.py | 18 + bot/keyboards/reply.py | 0 bot/keyboards/reply/__init__.py | 0 bot/middlewares/__init__.py | 137 +++ bot/middlewares/banwords_mdw.py | 337 ++++++++ bot/middlewares/error_mdw.py | 674 +++++++++++++++ bot/middlewares/logging_mdw.py | 350 ++++++++ bot/middlewares/referal_mdw.py | 544 ++++++++++++ bot/middlewares/spam_mdw.py | 575 ++++++++++++ bot/middlewares/sub_mdw.py | 553 ++++++++++++ bot/middlewares/time_mdw.py | 311 +++++++ bot/special/__init__.py | 1 + bot/special/text_processing.py | 290 +++++++ bot/states/__init__.py | 0 bot/templates/__init__.py | 1 + bot/templates/message_callback.py | 818 ++++++++++++++++++ bot/utils/__init__.py | 38 + bot/utils/argument.py | 688 +++++++++++++++ bot/utils/auto_delete.py | 636 ++++++++++++++ bot/utils/decorators.py | 812 +++++++++++++++++ bot/utils/format_time.py | 523 +++++++++++ bot/utils/hidden_username.py | 504 +++++++++++ bot/utils/state_utils.py | 650 ++++++++++++++ bot/utils/type_message.py | 613 +++++++++++++ bot/utils/usernames.py | 409 +++++++++ configs/__init__.py | 3 + configs/cmd_alias_list.py | 363 ++++++++ configs/config.py | 224 +++++ configs/mapping.py | 163 ++++ database/__init__.py | 39 + database/database.py | 115 +++ database/manager.py | 582 +++++++++++++ database/migrate.py | 51 ++ database/models.py | 254 ++++++ database/repository.py | 798 +++++++++++++++++ locales/en/LC_MESSAGES/bot.mo | Bin 0 -> 456 bytes locales/en/LC_MESSAGES/bot.po | 58 ++ locales/messages.pot | 56 ++ locales/ru/LC_MESSAGES/bot.mo | Bin 0 -> 530 bytes locales/ru/LC_MESSAGES/bot.po | 59 ++ locales/uk/LC_MESSAGES/bot.mo | Bin 0 -> 530 bytes locales/uk/LC_MESSAGES/bot.po | 59 ++ main.py | 172 ++++ middleware/__init__.py | 2 + middleware/loggers/__init__.py | 1 + middleware/loggers/logs.py | 364 ++++++++ middleware/validators/__init__.py | 2 + middleware/validators/email_vld.py | 24 + middleware/validators/url_vld.py | 42 + pyproject.toml | 43 + 109 files changed, 21165 insertions(+) create mode 100644 .dockerignore create mode 100644 .env_example create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/PrimoGuardBot.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 assets/photo/default.jpg create mode 100644 assets/photo/start.jpg create mode 100644 bot/__init__.py create mode 100644 bot/core/__init__.py create mode 100644 bot/core/bots.py create mode 100644 bot/core/webhook.py create mode 100644 bot/filters/__init__.py create mode 100644 bot/filters/admin.py create mode 100644 bot/filters/callback.py create mode 100644 bot/filters/chat_rights.py create mode 100644 bot/filters/chat_type.py create mode 100644 bot/filters/modes.py create mode 100644 bot/filters/msg_content.py create mode 100644 bot/filters/spam.py create mode 100644 bot/filters/subscription.py create mode 100644 bot/handlers/__init__.py create mode 100644 bot/handlers/commands/__init__.py create mode 100644 bot/handlers/commands/admins/__init__.py create mode 100644 bot/handlers/commands/admins/all_cmd.py create mode 100644 bot/handlers/commands/admins/ban_cmd.py create mode 100644 bot/handlers/commands/admins/kick_cmd.py create mode 100644 bot/handlers/commands/admins/pin_cmd.py create mode 100644 bot/handlers/commands/admins/settings_cmd.py create mode 100644 bot/handlers/commands/settings/__init__.py create mode 100644 bot/handlers/commands/settings/set_description_cmd.py create mode 100644 bot/handlers/commands/settings/set_name_cmd.py create mode 100644 bot/handlers/commands/settings/set_widget_cmd.py create mode 100644 bot/handlers/commands/settings/settings_cmd.py create mode 100644 bot/handlers/commands/users/__init__.py create mode 100644 bot/handlers/commands/users/admins.py create mode 100644 bot/handlers/commands/users/conflict.py create mode 100644 bot/handlers/commands/users/emoji.py create mode 100644 bot/handlers/commands/users/id.py create mode 100644 bot/handlers/commands/users/listwords.py create mode 100644 bot/handlers/commands/users/notifications.py create mode 100644 bot/handlers/commands/users/report.py create mode 100644 bot/handlers/commands/users/slience.py create mode 100644 bot/handlers/commands/users/start_cmd.py create mode 100644 bot/handlers/commands/users/stats.py create mode 100644 bot/handlers/commands/users/word.py create mode 100644 bot/handlers/messages/__init__.py create mode 100644 bot/handlers/messages/default_msg.py create mode 100644 bot/handlers/messages/ping_test.py create mode 100644 bot/keyboards/__init__.py create mode 100644 bot/keyboards/inline.py create mode 100644 bot/keyboards/inline/__init__.py create mode 100644 bot/keyboards/inline/decision.py create mode 100644 bot/keyboards/reply.py create mode 100644 bot/keyboards/reply/__init__.py create mode 100644 bot/middlewares/__init__.py create mode 100644 bot/middlewares/banwords_mdw.py create mode 100644 bot/middlewares/error_mdw.py create mode 100644 bot/middlewares/logging_mdw.py create mode 100644 bot/middlewares/referal_mdw.py create mode 100644 bot/middlewares/spam_mdw.py create mode 100644 bot/middlewares/sub_mdw.py create mode 100644 bot/middlewares/time_mdw.py create mode 100644 bot/special/__init__.py create mode 100644 bot/special/text_processing.py create mode 100644 bot/states/__init__.py create mode 100644 bot/templates/__init__.py create mode 100644 bot/templates/message_callback.py create mode 100644 bot/utils/__init__.py create mode 100644 bot/utils/argument.py create mode 100644 bot/utils/auto_delete.py create mode 100644 bot/utils/decorators.py create mode 100644 bot/utils/format_time.py create mode 100644 bot/utils/hidden_username.py create mode 100644 bot/utils/state_utils.py create mode 100644 bot/utils/type_message.py create mode 100644 bot/utils/usernames.py create mode 100644 configs/__init__.py create mode 100644 configs/cmd_alias_list.py create mode 100644 configs/config.py create mode 100644 configs/mapping.py create mode 100644 database/__init__.py create mode 100644 database/database.py create mode 100644 database/manager.py create mode 100644 database/migrate.py create mode 100644 database/models.py create mode 100644 database/repository.py create mode 100644 locales/en/LC_MESSAGES/bot.mo create mode 100644 locales/en/LC_MESSAGES/bot.po create mode 100644 locales/messages.pot create mode 100644 locales/ru/LC_MESSAGES/bot.mo create mode 100644 locales/ru/LC_MESSAGES/bot.po create mode 100644 locales/uk/LC_MESSAGES/bot.mo create mode 100644 locales/uk/LC_MESSAGES/bot.po create mode 100644 main.py create mode 100644 middleware/__init__.py create mode 100644 middleware/loggers/__init__.py create mode 100644 middleware/loggers/logs.py create mode 100644 middleware/validators/__init__.py create mode 100644 middleware/validators/email_vld.py create mode 100644 middleware/validators/url_vld.py create mode 100644 pyproject.toml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..52c1e73 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,52 @@ +# Исключить скрытые системные каталоги, но не всё подряд +.git/ +.github/ +.gitlab-ci.yml +.gitattributes +.gitignore +LICENSE + +# Виртуальные окружения и Python-кэш +.venv/ +venv/ +__pycache__/ +*.py[cod] +*.pyo + +# IDE-файлы +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Тесты и документация +tests/ +test/ +doc/ +docs/ +examples/ +README.md +_count.py +*.md +pytest.ini +.pytest_cache/ + +# Логи и артефакты сборки +*.log +*.logs +*.log.* +*.logs.* +Logs/ +Log/ +dist/ +build/ + +# Примеры и шаблоны +.env +env +.env_example + + +pyproject.toml +poetry.lock diff --git a/.env_example b/.env_example new file mode 100644 index 0000000..c2311c2 --- /dev/null +++ b/.env_example @@ -0,0 +1,253 @@ +# ╔═══════════════════════════════════════════════════════════════════════════╗ +# ║ КОНФИГУРАЦИЯ TELEGRAM БОТА ║ +# ║ ║ +# ║ Инструкция: ║ +# ║ 1. Скопируйте этот файл и переименуйте в .env ║ +# ║ 2. Заполните обязательные поля (отмечены [ОБЯЗАТЕЛЬНО]) ║ +# ║ 3. Настройте опциональные параметры по необходимости ║ +# ║ ║ +# ╚═══════════════════════════════════════════════════════════════════════════╝ + + + +# ═══════════════════════════════════════════════════════════════════════════ +# МИНИМАЛЬНАЯ КОНФИГУРАЦИЯ (только обязательные поля) +# ═══════════════════════════════════════════════════════════════════════════ + +# [ОБЯЗАТЕЛЬНО] Токен бота от @BotFather +BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz1234567890 + +# [ОБЯЗАТЕЛЬНО] ID владельцев (узнать: @userinfobot) +OWNER_ID=123456789 + +# [ОБЯЗАТЕЛЬНО] ID админского чата (узнать: @username_to_id_bot) +ADMIN_CHAT_ID=-1001234567890 + + + +# ═══════════════════════════════════════════════════════════════════════════ +# 🤖 ТОКЕН БОТА +# ═══════════════════════════════════════════════════════════════════════════ + +# [ОБЯЗАТЕЛЬНО] Токен бота от @BotFather +# Как получить: отправьте /newbot боту @BotFather и следуйте инструкциям +BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz1234567890 + + +# ═══════════════════════════════════════════════════════════════════════════ +# 👤 АДМИНИСТРАТОРЫ И ID +# ═══════════════════════════════════════════════════════════════════════════ + +# [ОБЯЗАТЕЛЬНО] ID владельцев бота (список через запятую) +# Как узнать свой ID: отправьте сообщение боту @userinfobot +OWNER_ID=123456789,987654321 + +# [ОБЯЗАТЕЛЬНО] ID чата для уведомлений админов (куда бот будет слать логи о спаме) +# Для группы: добавьте бота в группу и используйте бота @username_to_id_bot +ADMIN_CHAT_ID=-1001234567890 + +# Дополнительные админы (не суперадмины, но имеют доступ к командам) +# Необязательно, можно оставить пустым +ADMIN_ID=111111111,222222222 + + +# ═══════════════════════════════════════════════════════════════════════════ +# ⚙️ ОСНОВНЫЕ НАСТРОЙКИ БОТА +# ═══════════════════════════════════════════════════════════════════════════ + +# Имя бота (отображается в /start и описании) +BOT_NAME=Первозданная Жемчужина + +# Описание бота (длинное, до 512 символов) +# Если не указано, будет сгенерировано автоматически +# BOT_DESCRIPTION=Бот-модератор для защиты чата от спама и нецензурных слов + +# Короткое описание (до 120 символов) +# Если не указано, будет сгенерировано автоматически +# BOT_SHORT_DESCRIPTION=Тех.поддержка: @verdise + +# Путь к фото профиля бота (необязательно) +# BOT_PHOTO=./assets/bot_avatar.jpg + + +# ═══════════════════════════════════════════════════════════════════════════ +# 💬 НАСТРОЙКИ СООБЩЕНИЙ +# ═══════════════════════════════════════════════════════════════════════════ + +# Режим разметки текста (HTML, Markdown, MarkdownV2) +PARSE_MODE=HTML + +# Префиксы команд (символы, которые могут начинать команды) +PREFIX=/!.&? + +# Отключить звуковые уведомления при отправке сообщений ботом +DISABLE_NOTIFICATION=false + +# Защитить контент от пересылки и сохранения +PROTECT_CONTENT=false + +# Разрешить отправку без ответа на реплай +ALLOW_SENDING_WITHOUT_REPLY=true + +# Настройки превью ссылок +LINK_PREVIEW_IS_DISABLED=false +LINK_PREVIEW_PREFER_SMALL_MEDIA=false +LINK_PREVIEW_PREFER_LARGE_MEDIA=true +LINK_PREVIEW_SHOW_ABOVE_TEXT=true + +# Показывать подпись над медиа +SHOW_CAPTION_ABOVE_MEDIA=false + + +# ═══════════════════════════════════════════════════════════════════════════ +# 📝 ЛОГИРОВАНИЕ +# ═══════════════════════════════════════════════════════════════════════════ + +# Включить логи в консоль +LOG_CONSOLE=true + +# Включить логи в файл +LOG_FILE=true + +# Директория для логов +LOG_DIR=Logs + +# Имя файла с общей информацией +LOG_FILE_INFO=bot_info.log + +# Ротация логов (размер файла для создания нового) +# Примеры: 100 MB, 500 MB, 1 GB +LOG_ROTATION=100 MB + +# Время хранения старых логов +# Примеры: 7 days, 30 days, 1 week, 1 month +LOG_RETENTION=7 days + +# Выводить информацию о старте в консоль +START_INFO_CONSOLE=true + +# Выводить информацию о старте в файл +START_INFO_TO_FILE=true + + +# ═══════════════════════════════════════════════════════════════════════════ +# 🌐 WEBHOOK (опционально) +# ═══════════════════════════════════════════════════════════════════════════ + +# Использовать вебхук вместо long polling +# false = long polling (рекомендуется для начинающих) +# true = webhook (требует публичный HTTPS домен) +WEBHOOK=false + +# URL вебхука (обязателен если WEBHOOK=true) +# Должен быть публичный HTTPS адрес +# WEBHOOK_URL=https://your-domain.com/webhook + +# Секретный токен для вебхука (генерируется автоматически если не указан) +# SECRET_TOKEN=your-secret-token-here + +# Хост для uvicorn (внутренний адрес сервера) +WEBAPP_HOST=0.0.0.0 + +# Порт для uvicorn +WEBAPP_PORT=3131 + +# Уровень логов для uvicorn (debug, info, warning, error, critical) +LOG_LEVEL=warning + +# Включить access log для uvicorn +ACCES_LOG=false + + +# ═══════════════════════════════════════════════════════════════════════════ +# 🔑 API КЛЮЧИ (опционально) +# ═══════════════════════════════════════════════════════════════════════════ + +# Различные API ключи для интеграций +# Заполните только те, которые используете + +# Общий API ключ +# API_KEY=your-api-key-here + +# Web API ключ +# WEB_API_KEY=your-web-api-key-here + +# API ключ для погоды (например, OpenWeatherMap) +# WEATHER_API_KEY=your-weather-api-key-here + + +# ═══════════════════════════════════════════════════════════════════════════ +# 👮 ПРАВА АДМИНИСТРАТОРА БОТА +# ═══════════════════════════════════════════════════════════════════════════ + +# Разрешить боту редактировать свой профиль при старте +BOT_EDIT=false + +# Анонимный администратор +ANONYMOUS=false + +# Управление чатом +MANAGE_CHAT=true + +# Изменение информации о чате +CHANGE_INFO=true + +# Повышение участников +PROMOTE_MEMBERS=true + +# Ограничение участников (бан, мут) +RESTRICT_MEMBERS=true + +# Публикация сообщений (для каналов) +POST_MESSAGE=true + +# Управление темами (топиками) +MANAGE_TOPICS=true + +# Приглашение пользователей +INVITE_USER=true + +# Удаление сообщений +DELETE_MESSAGES=true + +# Управление видеочатами +MANAGE_VIDEO_CHATS=true + +# Редактирование сообщений (для каналов) +EDIT_MESSAGES=true + +# Закрепление сообщений +PIN_MESSAGE=true + +# Публикация историй +POST_STORIES=true + +# Редактирование историй +EDIT_STORIES=true + +# Удаление историй +DELETE_STORIES=true + + +# ═══════════════════════════════════════════════════════════════════════════ +# 🚫 МОДЕРАТОР (банворды и фильтры) +# ═══════════════════════════════════════════════════════════════════════════ + +# Файл с запрещенными словами (JSON) +WORDS_FILE=banwords.json + +# Директория для постов +POSTS_DIR=posts + + +# ═══════════════════════════════════════════════════════════════════════════ +# 📌 ДОПОЛНИТЕЛЬНЫЕ НАСТРОЙКИ +# ═══════════════════════════════════════════════════════════════════════════ + +# Добавьте сюда свои кастомные переменные по необходимости +# Например: + +# DATABASE_URL=postgresql://user:password@localhost/dbname +# REDIS_URL=redis://localhost:6379 +# MAX_WARNINGS=3 +# BAN_DURATION=86400 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5a679a5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,97 @@ +# ============================================================================= +# Git LFS: большие бинарные файлы, модели, архивы +# ============================================================================= +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text + +# ============================================================================= +# Автоопределение текста, окончания строк +# ============================================================================= +* text=auto eol=lf + +# ============================================================================= +# Текстовые файлы (Python, конфиги, документы) +# ============================================================================= +*.py text +*.pyi text +*.ipynb text +*.html text +*.css text +*.js text +*.json text +*.md text +*.yml text +*.yaml text +*.xml text +*.txt text +*.cfg text +*.toml text +*.ini text +*.env text + +# ============================================================================= +# Изображения +# ============================================================================= +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.bmp binary +*.webp binary +*.ico binary +*.svg text + +# ============================================================================= +# Шрифты +# ============================================================================= +*.eot binary +*.ttf binary +*.woff binary +*.woff2 binary +*.otf binary + +# ============================================================================= +# GitHub Linguist (указание языка для отображения) +# ============================================================================= +*.py linguist-language=Python +*.ipynb linguist-language=Jupyter Notebook +*.html linguist-language=HTML +*.css linguist-language=CSS +*.js linguist-language=JavaScript +*.json linguist-language=JSON +*.md linguist-language=Markdown +*.yml linguist-language=YAML +*.yaml linguist-language=YAML diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fcdd9e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +# .gitignore: Игнорируемые файлы для Python проектов +# Подробнее: https://github.com/github/gitignore/blob/main/Python.gitignore + +### Python ### +# Виртуальные окружения и настройки +*.venv +*.env +venv/ +env/ + +# Кэш интерпретатора +__pycache__/ +*.py[cod] +*$py.class + +# Пакеты и сборки +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.eg +*.egg +*.eggs + +# Poetry +poetry.lock +.pypoetry/ + +### Логи и БД ### +*.log +*.logs +*.log.* +*.logs.* +log/ +logs/ +*.sqlite +*.db + +### IDE ### +.idea/ +.vscode/ +*.swp +*.sublime-* + +### OS ### +.DS_Store +Thumbs.db + +### Тестирование ### +.coverage +htmlcov/ +.tox/ +.nox/ +.pytest_cache/ +.mypy_cache/ +test/ +tests/ +_count.py + + +requirements.txt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/PrimoGuardBot.iml b/.idea/PrimoGuardBot.iml new file mode 100644 index 0000000..af007a6 --- /dev/null +++ b/.idea/PrimoGuardBot.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..7c04147 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..abb29b8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..89e5c61 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +# Базовый образ Python +FROM python:3.13-slim + +# Рабочая директория +WORKDIR /app + +# Копируем requirements.txt +COPY requirements.txt . + +# Устанавливаем зависимости +RUN pip install --no-cache-dir -r requirements.txt + +# Копируем все файлы проекта +COPY . . + +# Запускаем бота +CMD ["python", "main.py"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..825ccc4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2026] [Verum] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e963fd802188e89b98f08709dc1864b21eb8a6b8 GIT binary patch literal 26688 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 fQ)_qw`n3X{X862mYv z3=4_b<`~^S z6*($+bpH}Leo|OS_~dbE(Nm{HrO!)ANS&9zbV*)aRo&Fojpu*=f8hV`0snpnjtdC% z2)*ayIS=q2=ixif^Y0Hp5&-yk{zriSCp^4-2M+Qd68Lu#5ctnX0NA7RJmWtKh<&s9 zDU&}iTgF#zEk|Nm8EBMiI6M-gPT+qqsg(M3K|_~qq`A2i8^YqUZ>)_zF4ZeXnk1qy zQc~bpJyKq+I!g0cI;bY3iZ?0Uh26Y^yy^za(POmx;$)L`T);*r8 z^m=#C7*}emRTP{9%0RVPH9R^7cXaiyB{`td-O~_F)j=O}34+15Xt)AUPbOkO{=U77 zYsCX8zK5T?9O-4J>R!8NVf<0~jPS4fRtu>=545^nxF{C;fv`ZvbR_igN!;UQ~A#BKj(Gj?IfsP%NV;}jS%6)WK6NEbs? z@!EIs2vkk8<$TW!3SUFnowG2d_W47blEHEfpsND4jn%#94qD`|v1-%q@q+S#zO?~Zt?ywOr}>8V46 z;w{M)fy_TE( zhSiDq*86SQFw5EZ?$dg31j$*l(Z2GWYO=07}#O|eebLA=BzQ#ISYOPK$uS$ zNI3rXk*qOjMSJH}R^iWglf1|$40wBoK9W_cNeQ@q?Tz+#FMak4bTErl2t_k}-rTc!J>4Vidh0x%?v*n4f=H;NInW2k8y-}upVUp4wbtSOA>|BimCm)aw(ng( zCGVM|%ayoXD}D# zh^}omuNHF3?+y#(Dxy_M#HEpzTc1C)R#-{t0vF%x8*E{8VE>)_0S6N9hI-Z+IlyakXrUD1=D}S+29W}CKT60 zXoCC#^_&f}{;7jGHI|xu;{uA$%en;-pbCv(FVdaJnAW!N{|pCWaK-*ZlU~AK#ioBw zf}n&DwSny*Q4PIIU#eW2j9VWBXi&5Z$jRw$ns~3lg)JC}uh)7`TYRZJAG{TQ8@)DW zgPp{tvPSRmSq@iQ%|p-p6Z)fE{)~|WU*%Jk?gM2;FFP+qmXBq2dyBa%xt46;G}i)T z<5rtL$vI*blgP07y8%#{(P&vR&4^nNseCy_-R2`fexW%ROgU)=#da z7c!+Io zUudvJ{(;l0@3?y_anBYE)LdJv zi)rZ0gGYJH&GI@iQBjf9p^ACi=ER;kyOb)DwK|=6z3ydx!Ad_AF2TS~i3b%szQ#by z&*TRVWKXuddOzUrY^T<8;np29ZDDO^(Q;~Neh3&$iMV!NTYV<5)~i5y%)Q_SoICaE zj8|mv%kgi#7kPjLVc@JVkjo1Qzquqvu%39jh)eHdCf)K;J`w!VDWsY-6y<&meL~LW zMgh`gyw|2~%5U`Q*R{o0`3{lw=HOD7g?SoIPqj1r6VGc?#_9Qp(>fno74STQX5VYg zJ?t2y;3|YfFsdr|Kidz@@4Cy-JM=c+*+~JwF~Qs`wO+WTZ4U&yh54E1o4$DC!iR)+ zlM7c}e$m=TUH_ojuss>U%$DB|$<`{%li`btloB?bF%uNYV30vg%Mcitm`}M!xNuFz z>4xu1TgZ_-g#fR9haex7OrI>PlF7RnFUaWi?6FVg{D*wF6nu`pI?6Gx!>OsuSvP1D ztz~ud0Pn5;G)n-0>t_Mr#l;PRcT@fbCYeLHa^ljla{~^yV&m2<$lw03(t_$Qj#_o~ zQ&s&n1zFh#Yc+2>liC^Hx``#^K1lG>%oQhvKlpTphXxuA(A8 zv7qZF)>GH;M=#b;W-c|v8m_0*PnnoWhmS7fhbE}mi0L%0D}y*4!?9lV$L5J5Z})Rg zhXqEooDZLI$_`_UUV5qHt0CX$Z}}40Hlm>T*&$I8EWU)n8Jw?x)|#xaYKk=%3#z0} zz5@=tN#Fs#3Lj43J+U8(uPqb!s>a|jQ2dQJr6;_X&X@Oe6Ww!a$-YmRQ}tPH_DLpo z`AOAi1-TJtR_k!U1U&dYVy$b^Tri&@X`B~)@Mv-BXG;mI@~VONA`Zds&m9WFBfS$V z=$9${o9!X72@O|SxKFZzGDA!lUuzivHHjLg#9bDuC|iE4V`kf_ehU6 z;wqq@PTHZT?EHj*cgFj%P;B2PgwLA+0=ElN=A!F`N)cq9t)Wmq?Ln_6;^AbQ^XHo z39GG$k;mXWk#MR=9(XB(uPA6uLymr6PMrNy%opiwJab*Zk5D8{F#9y-g05DR_OAO& zD;#fXPafp{g-TQfP1uYB0w;`s+=Tyh6h3iTh4*-_!0)vg8YtaEcS|=Wy`abQ$p`Bs zA>YL273#Ws{&VX#WZ`tF|3o^SNrq@m7u|%s)iuILg5pf<<&83&w+r)cZq* zs^-t=Ffe1$9yViBcTAv0XN6x10OEj=iZXEE@VSJ9gU79BsnPH#LmjDDgY;Sg(=EqH zJcN)etfOf;y!CjyixC>~@=U%@=8#^4W+zz5zxq(Kja#Bwp^xSLF`u^uVXsZRJQoUt zWe=1Pt%4a062Yks4)1Q;#(nZuN%0dA`b*_a#m{Zpz&pl>o@6gaS&rRYH2X}-25C|}pY!cQ@$u%qmcWSQAX@ z4OP0K!0T0#==rMg@DbC)#DL}68&37H^dL9pL@Do+quHkm#DMPoV9ktiLz*Kd@HttG zm5K!qhri}AXFd1fdL+Wx+nbSS%b5pteA(7jr69LNAjquJgO?{QY}9@)B;^0mZu_+1 zK+C*yGMlFPIgkORGnJYREiidnAO~jHY;>`i1A%oX zp0iHbRGu&ir>Gx!bK;_f-2uB`N)>wd*ve`jq@2$apt?FLd-0$A4~XeF$!RTJ7U#k< z60^NShE1pw0RXYX=yOZI;tuWdcbwm?rtWE?zvV53C-kvPe2q0GPn?Ivq@@u=E2`&V zn0mw4YJKkTTLFX8h(Dx>#W|9D&0hm_&u3MVTiTR*?qI=HER{F%T_N+6DJ!sGF=`g8 zg?)a;Oj$1|P!0mwkaDc9nzJ5r*8QR}iBdTOh2GP74wrsWvstX`Wu%fIaNVY7zq3jJ zfS=tuL8W=0a0l;s#Bi_ z9qtpT`QrPXtk96SS zeuoj1ny?Q{a#3=6Kdz4}q{1=Sy0G<_OYlqZ1OSz!w{zT%yj|bw4bIL?$R#<&?-lum*pJFsU2kR3vL6nnJ?ZrUpR|1DnEg=|b^YTo z!sUVY(VSZXZ&i+|Ps%e~;ZEjYN}z?yloz(;4|^5jOOb4KP*6W^;w2&Bx$iRFF0;7K zW}zJXOlPwulal`8uTpIanon4s_qlagOmi(wMyC-c6nVZ)n3l&5u+a^$A?svF?u8&2 zp*u6=A|!mO(2YY26-=I9r!KSp>cm|8`ye*nZj|*mM@x4&DwH6>-b=60)%m>gL7~bG zce@xeV|J&sy6Uzhvku)r&>-B~l4MPOO;fx#-TdAjKhmd4DSdEqz`st`y2{ltHowb# zLH{IurD&@| z`lcbV{1K@%{a+QjT1P9@UmHt_JDgrUa_Vf^#f$kOjop32&)vHsND-eZeDyy;TqS-O}CzVW}VoV0^tEW}=V z`KWZ_#cpRvm=`0~Fs?W=utGYgT)$=DU1nYc zIX_k>LNec>bWclc-tRqiGYbnE1TWP^F;QNmlGY$VbM$bk<*3mrdawXR`tk@!u=10* zag6aGoTbLdcoYHAuO@&U`r*~R?x+}ST4tRJ$uoF=ghAQ|=N)tRm|9_!W6aK;jnrgR zy-exfA_CTf9bez=li;85t;8}t57$Q3THy@NnDlf;2|V0b8FeTOgu3<(s;0z6Dnj?&1vFy}mLI;W>$+3r&2_!1@8vCyU9mA-k6)=N@Et45ytG+mJjDC zYF)&;1p$|J*kjYV;IKbVwpQ-jEHjX#4%yb$Ed7f7M7VbvLhpwcSgov9mq%1mZ;S3e z>G08C@P`0!Jm{@Lf->M|ByiJ+SJ<-S0u4G79HKhP>T3{qpS+r`AMl{Ad^R@~zA>k( z!wE#SUOi+z-#8qi7c`lgvPryOO}1hszrC!ReO64?Sfm8`eDsv$WW<2k#4?Ap(b}p^ zNeoUK#OOkPlL~scg<8W;QXY8)eFT8*ufwl!?^M$a)dpA9aEWViO8vCe-J;P1fM1zM zmbzV`rKDxcAA`smC^5=}tdTxt21bTk`Rd&N<-M{~;X#b)kY?j>`e!l^-S~|$tf4bo zw4H8P!@*Nh5;#Pnxsn#5sDc5A0MN#H-8ntf9i3%D^*B#)Ly5tsIYO`Velb8JFnl%4kYCKtBKguiwAgnD;mu)a=kUEPCMN-%;(VPK;E3QDB#!}6Wj%t?8?r9uA{Ss2#ggn7*bKa0^1WUUbK}pLpYF$D7Pqk&d;eSOkDc= z&(q~u<;p|(RY6|(2bl>bH4P+mO9gmio{&-6kyDD2_BuQ9oQF>N5TN0EUaw2KU6rIxieGvtf4eV_lIJ6U|x3PymB&aaDVW+ zaOlGwa=n_XJ%3J~*|TCW^>NVW!OT+U%HDv*N->>qb0l|Vxij4|LTuuCQBcm4fuYADx;}kNu*EN0 ztj6DDY!e;6>Ey_Pz5BAULdUM|)<<`fBJKpgi0DZ<$(v^i)uw`7za+L&nK@;Fh@Vt^ z*-CFGg;W>yaBF#mNKHgYNx^GARF5?t@dj--FGdH}jf@Yy1OQ$Mzx{DKPw`XJrvUGD zOU{f2E*91n_1!uar*OeZpDp2WP(e{U?PfeVE$vu6n!j7 zbCgfafs$iXeEk$OTZ}RTR>3v*#_mFkYzH@^IZ(DeeJH_Xzop*yo4`-T7tzhk| zm?%!5lH9c0czwyv*3ZRV4;**8alZg66VSbv)*XcdKLdNbB4&)Ax>*hkzaH!vh*0v#gD*c)&gA8_` zq<{a%KLHRp0vrI80ndx?0N~bHW?aNym3KqWYgM1hUV}YWC#xvvgakc^XnY+} z_gaC@i#T}eHlkb*>@bk@G5E(R`*DlQ5cHhv0BIPOQ?=gmw;bZyk2)mc?I(Jx+p$%`VH{;L0z(?*(UR*ET=a@2Jbj18uoZV)AOmjzv z%;nd|)e>brB5w(@94urNU6`NQae?t>AZ$>Jri(H@?&mgSnK8S-`unjKeV(hCs?mzq zN6UIx`bypW=g9DPL{kVzCDZgAH9{`2)?aX&;~!CAIz}W^&&I^Y>O2S}x*~KH-36n` zb(5phHK=Qwq1g^tu0(hMDtw=c;D0j?oCQ3A9~Ykk=XBn}kO#+f!>Lc9x3c6W&)F{} zo(|hyGrh4EWtIbT$T>Zo$qIAG6GxqYQe~fat-=nf;P8S!^VkFA{nvIPGXr%yY-B|1 zM`kQGYM(1&O#=3pU&>2q?qd${{aFzwgQ2OL&4tu~4%ze>H_3aEP+a_v*o}q1>GluA zfWt}W%==>g1q`Gxg}IEvVp~JasVNk+;U6{2jH29*tEJ_fJ)fo;2r~rhgOhf!Xw}n7 zW&P@FZS7fPr@YWOLtmD3m> zi1~PVI)el!WW3aC9KlRLZ;Kx}NYGpPNo(@^Wm5y3KmmNha`v|`em(F!f!FLkj>dVR zMb0^maG{ppJayL!ls0Xs2oD`}jpj==fk>@ni8Bx*IWJ4gbi|{Yiq-Vul|9xKcTOX_Q1=1zkXPJ zELEM?SVZ{MuhlPw20m{2Td-<>ywUv}O$wu$<|KW${jr0m20E5ss=<+FUQ*D)D|tzlw%bwFO8vC1!fA+uzEMyOhf z=TcGj6ij3kohZ%zR%9lL3eaJ*tE<0M&i}3>z)@|oMQ7Cd!dZH{k)$HiKs`J4h~XDv z-nd%Xb0z%{{(OeZ#w~}s)`!PYpm|2UL0NHK^~4p&cLI5lY8juPeP+qDf*Rw4ycn5{I+;34 zqcXOZg0g~qv+dpu>r`#b!&x(+6ZZ$wui+usY3%qQK{{sFIxr4TeRh#-kRQU}-no8! zXz5<9snrxD^n(2BYXc0>rh;`+;WKM<)jvr})p^%rb@=FG5PX4tt1f&pV&b3{s1knw z4*rR(9q_YuILiMj{4nZh;01k!r(!?Kgb(9zbDNRbGFoRxSzZIJ9|AH^3tmq*z9NLZ zErM6avQ&uP8Qvr4MOW*?vrtDd_POZ)6D-J|}TH?Gd!5;WzV`kIVAbY_RIW>zRfMH%-d5 zEKnwc9uX0)!@t?4Sa6ZZy#EjAcOrt`a6VuapW+3tvS>(AB{k0Bq_nQMLPxY|snM;! z8I8H!-u)Gql1OobsLA7xs>Ci8(#LuEN6HcYM%}#cjE>i9eT_D};j$eg_c|o1d#I3> z9=xVj)HkeFxHyTpzEooSf%-_Hsdk@QxjUd$f(Wln#O6ENl~b@bj|%(op&`ddrmdGI zW|6qa@~Qi0kMevJ1CH{jkVN%=F~OdJKD>Bd)-#4wO2-GyqflF(Uh zJZa&u*pR?&%iL`b5mL&U_FLsX}Lv$4=vxqUPD`l&KT6T>78+1|W@ zPaTw2^4Xy|<&hHI<76puPbBa>ybsIdUj6>l?wDzHQI|HCmhMr;I}ZAD@~gnZ{=C_T zd9%no$odjJh$fxxz`XC&>=;Ftb=6j?9$%!q&p%NStn}c>g#yH{vKLAQuU+0b7$k?4 z`d%(vbMKF#r-4-IQ=5WY3bvYHB)U(+`T(_xMtw_&Kcr+^%pj4>u2unuzb%g^oyyF< zW51XHoUri7YK}*2NOxd5XEh5y37$#(I_eoj=& zQPe@7`Bm@IcPd18t-KV$C_BP#>P^%H?WC8jU^K}OQ0F6A2;hkv6`?j49SYB9Zs0s> zN6YUW30FRzQB`v1l4hp$K{UXdbyeud-XwPcJ?5SHrmaos}hSt7*^oXu}O)iq4>^pEpdz{B@O`{ z{`$|-N8xiEW@A`j3;_+Dom*yO6y#qbK6;r2pilP7Pkrbusrt%uqC)=@$0lvnP>4)< zD%PKR`av$?O1))J#JbKQm!~%M?pXu1ewVyoPd40j&bfnZ1(S6eh0=4}Ye4zSA0o4J zYa8%BeC1PQ2z~P)$q(2^XP=$_3LJhimE64!8Y@80^Y19SH5}#q{uCMEIA*mrk~V-q znjd<Xe($-^x6crjY@=q+?Y z9*Xf`Xg~}odn>`2k!>#RosV|g=5rDMkx}^JD}6a;=X18})BDjA_SP9riqF7O`^>^9 zI@<)VByD0K3fe@oU;V4K!~l7y1!pKJMk3n>6$N(f80Em(TM+r&-<*E|iPD2= zxu`nU0%79aYab}a^tyu01F6dAA}RxdNVhvPbq?eQf_5E7@LWYe{6#n{5hsKKhvmc;C$|cT53pS=7ZF4sU=A(gqb{7x>>lwlcQM z%sk!Go2qNC-!j2*6~_H*56Z?IyZX6 z`Nuvu`w0m6nrqM5@!%tjE!KG#w_Z6hiyy$lJG1>4LK#@N!e;(hQCSlSz1?o2m{ufl zu#@FhWc+2P2*Pr>!eec&IJ_4J{mtn%eqI*o_;Hn@*ZNNL(sHlsG@+!JR{Df4i z!y1a7b~S^Jl8Le6E7&HenuE$=$$DtEOCX+@DIP5z8Z{-|5sYR%LUpST8x85*v=h3M zaNb)VRF7OK(gVYktel@ICkAuclPJeYV@T4=Q-lc}I3=77og9o*hot&9wfkCM zNHlQ2N0G?wSyaxMAQ7EUbLOl!FKFdt`}XpO);rnSv;-2#=rm_yZrY=|lEZkbo>YD5 zWM&km4zr0qh}JxB^d<=XOq=yqL1X%Ux+uQlQf#T9uD1DXR;zf)&i|ODPE5}d3p9X6JL3bpOY(y zlO?Q&S(z0KTaZTYehlv%?gqt4`bOgf&junHmukfsu^7pzrqOYZSKpsq!8k*cjPE$& z-+IyS+_lfFUw-H03gZ=bCA@zvC1%ClxdJ7iTCXg64Oisrwz_7%$ZBEjn)EXpMh@q` z`ffUAT7x5z2rs8xyukOC@c3X2mgdUZsOa(G&lfQ@oi<5x+U?v)Z$duZQiOSuVCNYGtBkFms$oSwKEl z3+ZU*Ens^gL~r4Rh=uw2>)KxrTlG&~dSw-q<)xk~shOI<*#mt4<*SFrC;!BR46cn;mFLr(V54YPFEOY-V0ZFZ(1 zm%g;df~%*5P5-u#Zps^C;-n2s+U_lZ&WBCk*OsOS^FNSV^6$u60%XJV?)R3Tpc9F*NBg&SB$>ea}UqbCoIG?<`K( z@s4|HIe52?U4hdBO~{~6G)mQyq@LFRE2Xt%tl*&+*6kCqIlf}@rAmUzC-hh0{kWqH z+~6rxD_StHf%(Q^4!oSwKRfnh^r(=N0In#xV2}`;ax%jTFNdh>`-#zw=74OAS1b*c zzSD4H!muZt?n8i`@7eX6!%{C;mbV3n!Jd+`g$UIU}pbSp9t7 zSe>gl1(&6P+KA_UF6i`yg)Nwiq6_mP-DZg+;V`kS4bkRe27Afu_!R0uviap!`7{s1 z=fjByvs?pm9GGKmyjkx;bBcPa?qo-jC)()4^|6mmRvtpaEQ~ExQDQ+1Hf-9E$b~~@ zJCbI`A{K!X;bZ94OjEQokDbtbi~3DtYvWl6iC={(jH7lD1vf=cLkopm|Ob4TfgkxjXW-YUhP%h zf#YV0r=ug-U#D3>cZ=4(kx#&B$&iBw|{s|^U<6-O5;Qe%P! zyGiVZh18o-pw4V^xQg)$G0VG|J(sGaW8Dj*5XiOSoa8Qh#g6xla+ziP6R5m$f#HM$ zk}`_G^Nc5hVdu_WIxHkFA(pDpI-((4#U!bRq-~jLPblgiOS8migZ8qP;oyU}HSNTP z_{7G)itq24d=-~1g8gD^8|tvsHnhVSGpYWhI+HPkka^f`I;wlu4Rv~-b~8v<1pDd@ zAI)5!YYrqSBEECyGJeiu3tI?9^NgxUmfO^f{ycjx&jlXVRU`@|}g#|ji}b`npse)V*D zX)8ACI}~kS{Q(ZPiTN^%Q%zM;i2TV2Kt`|lIQMgu8fUvs`chN`xoCRrh0@S*vGb~3 zRtxf>N->H5jIcp*GL|EhXFat(x{WJrdEc_&uV&;x<7b43~* zgeZj6I^N(do4g*nw3p~sWXOuvR-K(G2;dORd%1?s$+Wo^KS;P}xjwTtbitu+ORzpU zcN6<^71W`*YI;dU=ZBT4xY*nT#y|nCWUD5*!DwHw&x3c^GQ2aVSMJzft@fLzF3flO zYG6OGf=4x+Ft+E4@_Na2oIin$h$v&YP;4Y(lVp5l(5_GwuVeAUMt6w^iBZZKVmC8m z#?JhRjOG7jW)Tt>vCfiLxl`VH(6Y$?59n><3&l@4s`eM>2L%&x<;vi4&);RX+3?%S0<7&pUAAx_ z@%pKtOW9=9CPhN78SDm@QqeXI?K01!uFN#xv#VXH1+wsA7FRIt`sO+(u7R?^OqZqa z8p?dzRA=cUL!NQ#iMkzH274)e@tJXnL+v&x9csH0q#ei*IX3EV;3;^Z^EBr-BHTIu zch~0M=|r12b1A@57KAzv8PH7`<(ePlM$I^hW@U|fQCunKG z!2$3~ZoLhb0sW+9JAH$QlR@`=~_VV^htaL$T}G7dAH`82`wxc*W) zvg!8>X6`Rm)(}E^)>hI)s2Qf(NTj9w`G{`{U$KFr?W`Voc|Hfe@?Tcn7^#_Dpwk#k z5-F#5=66f%u}~&t5hs}9m`BYC9-GsTxS$Kphe!qK@lMHe4b^%mRi!$3=_~l;qM{+j zmre)5Ks4Hc;f}(F+(1A^3}UoFt2W65B@e;9-8jDGU0azITIsFt&CW5k92u8^Z&OU9 zOu=k)to91UAl`@A_M5&`**6f8fINSd9`~Box6z#UMcghsED2X+k+PvhFIZX|j@nsM z*s60wbR)?hh(z>-pp)5Pac5?Z&UzHC90cB-jtOUli=gxG;W7}9*OzUFVA_#O14AX& zhbnyXk2FqwD>S7ybP9M$6oP+dW{@Ba9ZDAp4_;l;zjisrAU=bfvX_WwtPLyU^r52} zXEx2;I`sR5R7&o@E^in9h0kbKU~YkeF)@U4A>DOjU13SoAJxf&Qp(7spZ8enB zVd4k|`b74(-kxVY4O7|J3XQ24ncavtUs{imq5li$&2Y>a(jKx?F^PwsCqZk%mWMV7 z!3aq;*DC0tJDnBR?emAcV+|ESRnjnfZ(681$dc96$0r^9w=RaYSg6;~S;ci*p^NEI zIl)Qw<^@iRFQxwlO8?BLusceyhnKM)wzRkl%kc)ge53QUZ6Vo_1=?y&!w9}!QkPwO z7FrUTcHW&Z3WaQoX%4+mLq5nIRP+L+bxE(bdM7Fw9Y7y{#<8n-p5>16NfL6BC%uncM5$QQd-uHt8Ar% z>k65u1YL|l3p47XT>&@bfl8|SHWCw69gJLaW#R-#L9RF&W|f1-uPYzsz1>jjEB}ft z$F;p$Kv4g^YL^uI>wc)5gj;hzHDsn$LONvQNvSX~kcxE+TWqc3FK@3m)4U8M z5EN)}k&=PTdQy9b=!&5hw@5E%xjpdb4sH39$GP@dks-66$@Mum&JZFpXP0VI$|JlS z9L~eFT>o;IgKG5#N8P49a^xy!O01JAs}`!q0viTN75(hUxU4*!QqdfA4cX=gFO-sw z{I)mI(Y2diK2)k$FY=7Ozq9wvFmP*s&$qn;rysl;XE5N?{A-DnqeUXtc%yQ1!^q|a zaTUYdQ%vW;YqxG4&pdel6v8|0+cLC*kSML~ystFcd2662>YZCD$ISoYDhKxdcHbxp**(o zP0Gk}hhFj}%fnouC|t6ll0>t+iA}xNn2%c?0J0vC~a4iupJ*nZ1+`aOScXkn=^=ek4Gsm?v&QT266tHx!;72j7x|du+5u^F|e(t z$L#IZf89M)|3~KiWB9(O6;VM#HQNL|Iwt#L z=u-J+bOml$xiCk){ONn4xok#P!Z5|jwWsUibO!lznD-1Cqclj$u{C_nnq5rW)%~jt ziXWcVqc#PL$Hi_Lc%(1J$S%p8VNU-G(3Y-op_udaHjf6jMpC7ECEM0g*t@dToxg`D zmv5+?IUoANNo>Z}Hsnsd*4rr9WCSbpK81XYi-BM2zE6yPUATHG?;i_Jhan|uZ3^=$ zh8u{h<9pFD`VkI$)e0HOQBk%~3dMMHElkz?yb z8blAYwC@ni%U*qGDjRDZn9k(Au@ zT#GMi=#JUZB6b#|jyEJWdW8m@WsDLd+wv8I9l0Q8UWj{betJzSK6#Mo5U89Zlt;CB zg3M<)q6;pk$YTTpXL24j(b%n}iA|DmHZKeQcy*AWFRe*zJfNV$=1QhOE*0HjeF8YC=^Q5H^4RF<`__;D*>X{KrQQVvO0UF7R@!V z)hbBNk8CCl-W*f3ZIh|{HOA4Vu^Q{G~FL7IR3`l_1vgJ(FhKJ9xRA6RYcJEBu-IM(zHcs^V@-bW&Q54yGI zH2*J9x#z_C=`Oe<1;ZJqTHanmt@;L}ftn^$_0vm!|6xVGpX|vJ`%S*4GAqu;{tH-C zbpGyj=v#yx4&PjAE_Z>AQn2vb3+`J;^&VPp_f}IMl|YKQxsX+TXP!oX98`~fytN() z-~LnU*H4a(R)6EtZKra%1+scSpXhV;z@0NJ=%5ZGRA*(Cz1<$D-hFW|V_c>13Y-(K zGQ|R07JOfLWfFr4lzxp2{&}JFCfBZuy(9f|Ti+n5E{*_NRVJ6;cR;ye^dtR0p-v?| zY}rs6Ay!U8hI6u}Mt`$eUcIv{FIo(F;t$LKXXuo?T#wpeF75>ecPNoLQ+hhgndFLW zc4v&&jj|=lDL#DgqgX4wOZtuFCBenvvo~;t#V+tD(`K$>t?eLW+a0mtov%DQ%j6(G zGN$wO*&$blIg7GHe2i>zye;CdNTN*EQs|$paG1&x3qBE(Xh_H8hVDgj7lUv<~HZFRmD%PN=Jc@%1 zQCrbzr1;^*BS&Xe4X$azrvyF8cTAqCf~MAj8ePKt$!^teNXce2`2^}wFyF*fiqr&?u`02P~CeKd=)x(3`Qn+|;% z++7yIR$`_@7GrE7JsYuUGjF#p{Fq>K#C>C@khVg>F+SuvvpP7Zp6hq+qtC_Dmp8l=x#xBNrJnQVPEXVkH+rj-^ zreCE%XLJ|W7`;MZk#i=6@9+jz5`F5a`ZAV&a|`?HxBZQaHLz@ldfTRvo#pV==_$o% zjC%f^hjY?yTs@nDu#Iru;>eiNi+TjaLgATB2j4r$MhHAE5{>ZoezM?l( zz-UC=2iaWw>_N^gUa@0JCUovm4h*gQ z6YKjSHJtM$eDgcK)LLZ>h4O#x9-0|$xA1v0&0>j0x<5xl3L2yBDt=AE7E;sk*2p+5)QuBWE^RIVBJ+R$BCVXK%&?klV{p z)0tc75K1Q1xp{kmVs_$U&P~)irVX^}z@mMPtznMNPT;wjCCA)ttZ#AWGSZ`TinPF; zC`5J?tb~X8uCx+GnfXx$MQy*yFD5u4A-ZEBcbOkYlcwKh2G?!P)V5&ux8WOlnp3QP z6l!14t<{A~dil7lfbzpDQ+{FK(QO;4sn^EE9m@GWBo>{9pCUbeyfGEABsK`~D$+w= zWdx?{x60;zk!}n51aC{~3-5e0;`Vc?RIK=H@MUPIt{uf)oxyAIM%jir!_emw)T*t& z+N~cvBZ>_09*b4NhcQS}HPTyn9zAPe@x{cYSWFwLw0G*IIGw*4o%)VXG<=Rd2Pkk?nXB zu#o?(h$KHxxTwr8Th+b$FW`wo;?pnS;t+oZJ#`o%9p*06q%Qhwkx3TX;af%Z%Y)Dy z$4fRrzKUMyi3)m;3F3@9k`uyp9~WOCr>~JUA|B5z!Wv<+#p$QBw1blLjlSqPX~^Ln zvmEt$<_V^bEgR4=w7zDw+{x_jup)~&mQpe*{5Ur(FG~kPWlqJ$NMhZ$(zO&G)9`~^ zb`{oZcCKT_m^0Z2!UFeuRy6uI7ShKxh}GGx`GQTvGk0y@?p}B{xJX$6{K|S5Zkw*IG<-cl(0laUxRX`4y*9b5n9@O#3)Z-si(V zZOsb$$@BP%JA7ozvu$qc?XbM-BoxB;Rd^sWI(+6lGq#0Pk)AU$l<#sS_Ee%ph7AJF z8$n3a0ZZH;DExX(@Se_U`KXYIx`3GaS1F4kubI%k0CM_okK+FFC5W!g?$&VQ<1gVD zB0|b#sJ&J_?uE;-5tl+Y+AIVfZ3BlC1ip0H2ulq-!^n0=c^Dcz-wc^&GJ4k1@7`a@ z%dr(QH!SUO(u!AS5JbhPrStUZ2Ppwh(Z5K3td=Hd)A&#qNsNE#*@%u7k*LOfZKrBQ zqiyR;5obA5U=F8{Nk{{oil|!iBL`O?h1rE8tXUk2bm-HJ-3KZM{8L|lDw`GO;e!~5 zgu|t@Mxl4_?T~wRWxs8$ZFFQU7CWmVGjq8i+D@ppZp^M*Jw1*bCse@c)ETsY;7WUy z`+q1p3%4fUw~dbwK>-m^8bN80?v~Ec-I61}GD1d(N=Qq`=-7l2(h>s^0m%Vl)EuY? zW1|EH3WC3P@BV@3ICebGbzk>&ea`a~1GT7iXKalN;i=C{vM!_c&M*In{VZ@Z=-TLd z|LN>BhC70=26Ol0VXLfQQ$8g{gvFe?mmRdafPX=x@;h})_iW;M6oJa#Y#o_+b&;pW zuSQ)=-cbMmB{DEs2MctB1^rRu&#QB!)Axm1*pc^hEJDpSr|*KdVc^kYaYHUdNw1(# zOgTpwh8n5z*=yWeC?xMIq4(yUTK|a(bxM|2u#?KAcQIVU_j`1Xq2eHq(*ZQ^Q0y2Q zd`AnNzxd-|XT1&P420{y+BmN07}^JwSP;Jy@|lHS#35DxyQqNpPmYb{D3v$m%_Boq z|H71KZ_>akT1#2r9%0qi-+zo3TQn}VPixMFd5j+(;m<9+jwcw z*}d&iNcjx$^4tc8&ONkHx)-D}m9~S@eW2PR3Rf7mAOG5pq5Z^%4&U^WW9z zj=KNOCJ$!`+3JrE7LPQI1B1LZAWEH~uH`{(aThziP0fpIdFOlGMKL3MW?ql`jOa=> z=09qabthyR2MXUsivFAxpBUenh9hKmm+PX=GbVuRtfIC z>Ht%>oTQ|{W(8$PUS_+4FP?efw~L?Qpa081MFf^E`r0*=%|Gb!)aJ*8Nw*{rniEdj!+|~4l;xu2pxn_8NHS^(WpH|pkRl@}vl4mMt@cclUNFpJ) z5i0mC@&vGjJ`UAbK%zv0R}Nb(x|$%OS$RQ-9lw=H)u#RegYL;mz*R% z6o9UJd>Q86T0WPWD%x6d7Ws>`sd$AleYjN71r=9kEiII}%PJ(A+?wu41qfhIkx5rv z$<`QtK0W;df3&Q=7o9|C2(u38BHl0iibIO&8RQFIrE0ClZO6F9SA2b-w6_V+Ur%d< zY6D(^BS|r`rlPm@tc>oKlL3OtrmnL}ti9ar z8WQDx4T*#O<;_vjdQrD^9^20cxw81-@&4Fj;a|*;)m>I|BvTKPrplrE0*}6wq#Brd zEqk-vd#1my?>)-bX=AZJ0@5m}+UdM9_o>`ccmGmyFm#Iz`)mfnBjg13g|(+Ds*GQA z0v*c^T+TKkhg^?cBqjd`&`sS{x@c*S)}u$a-i<)0OtVA$;FpwwwxlOhT`{D};XmDGcduJ#9HX>b9%#;Eo2z{jMNhY^>C52Tf1>I0#a8V1cbB z%?eRj+n0)Oxp6d~+R$2afZ}!rm(*k@o)3ALP7`*Bf|N^W5ljtGZMR=6qVggO^x;3a zi%GqB{afA)f<|RKnf8^4DSjZOM7bgCl#;mVKGcea#avQKq_8dh*Pb z(2@%q;NdZlS?#mOSFH^TU1PnH8MI?OC8e}c3rIQ@G=_)g(&{7tR7awQ)>>ZC}ZaoCwpqi-uvG9FZ$wfuVY$HF}(7>YV*?~fl8&IHCb051nIsN9HmKR?m~yp?F*nRuWy9sm5|%9Wi%PG~B2qYOKEs<-i>_38tC z#0oX2;Wsee`Dik=p>@zzgEu8?5PQd_L$x75YCK_Lk~~aV)>QgAT^%TZG(kSzP(Wkg z=A4jcGmDn;nHPV8Tz_qCkyO3a(C%461)v-#kL$wYX~Bh7+`k&-7FcB zO?&y}rj%34bzFX{OOR9TMSr#j=z`~k6MFQ(vYs7C)?pbw;0~%%B40B7$`{2=2M~?g zV$I#8_uug8am~o6B?2~efFbr#Z_xw&NYDb>z$unZD1Y+e!AgS7r3K<5Xrsjc)>-g6 zF%R2>=xR-5PkN|7nq)nl0_iFo8n%rh zKE9)se?jQZ>8M{#dn-8%7u|;{-&R0S^y9Nkbfi>rfMt&0Yg2R7Fzq zSU-*FiMv}ae?8?G)9ZXfx z`cr+bajK*>%h<#M`d-t7#^1A@vw^|?0jNsqIIBhKaU1_|l6LNJl* zD_i347-rvX9w!`Lu-RX^RzOdQCJTGv+Uq9Gi)HWLOmIuoTZyZmVWw;q%Osda1UAAt zD+u_%?phAL?wXwD1|%D_@WM;%(4UK|!ydeQV*=v_3I#UgNq$TBx;n#H5r8(Ie`TyU zV}=*eGk|a$un$6vzV8o?YWPKlWwiUQsdx`{N~y#teX1l(%xYSS)dIBOJvvHNF9y8IX zguT7CN^kb)a&Uubr6`Im1Eu^F1SpN#b7M9(7Q(B~xQDs@nM4ZLA!vWgPt@pzj1bQ7 zyAc{4=$}JXZED}H_VVX0QBpG#2HIy~Iv6aQzv&R%wpu^Uj8ObQHf8IzMtExq@lp!D ze0Z>R;Zdc~V^Wl|pLbmqeA13yJixapRkgW&`C`1Kj7Osf&$-(Wu=_anp)fV`8C7}X zAbVz4%TsC+OtE94TwHd1RH5mvH%mjwF7=zH(zR{GkE2n>rrzuV!VR)<|b zlQix|9UU4F#tn9Gclf!GhiCfgfsxzoEb8$DLp(9w(? zw~H32^Ff5r+4rL%-r2!_+1cj3c;`U}L!sXV%Qpy_YUk>khU;i`Ax|;svPEXEu@lE5 zDigmEoPDpzGclee%_q(UJAr%fga;nz2{A%l>DgHbPkafO2X0H$#pO1-zG<#U#=^hKOj zg#EZ2phNx7LV6zt-o6wlczODr?r;7xX z#p{FL7wSX*H2o7aa2(!snDreFa~0)(a=?Zp>(VHMbyNUH{#10QX5`=r>`_o`-x)-u zxA_;bpA_&j3nJbI9Ul4JmU`Mi8kU*0$p{Lcsy$GfuB+`L&IcFP$QGISb9efJFV=Ps zj$&3CF&JV@#aH(SiVl^s@DLPG`5qV#cQ7a=c9SlZP@hkc$Z0&P*PR;@b3z;q+GvGD z)B(-=x8A<%j{4E?QUzmb6s-{Jsx#+n|KS_dvgw`qdu@RcfEe98TGRb&tGTx&VA1!> zlHe??{IsjtFIOO&g^A$}jda2I6#LsemY8iBQGxs{mF~=@DD}C4a>Y1YoJNSc>L0cK ztFwj;NcnWD3}I0`KD0^^>h9(QMLh`GS#MYhKR;dmvsJS-$GgJ#4=!v`fm+A|8mz!V2{AdM%U=vOji0eq^oI2sTzq@|@Dx9hKmF}Crg>aQ@Oz14l~_}aqZ`KB;N{e={ca?!Py3Zo$k`@2}K9sKBS z|LOEJ7JKqs6Y=E&ReC-r6>A|pdoDZYZ_)#gmxG}19W3?UyO`w|9|n$^8Z^@gfD%*i*-OXdAWwzydgImS8A!*hV|3wC@@(2~mxR8Q3A9 zpKqk+Nu(yl;(%4R)|CX5^>=tAj6-gyV`m>MFJP4P3%_ zduR91r*7S4K6IE<((b9j>|;XYQ9V6tot)7uhi^Frce%ecNp7fk|DKe zt?{J~r7tSoSYr2x8AJcV^2s-=pXdG$EasOF{TXPd)A54kU%@jAf-}sk=r>^LdTsiU z${fQ|T$?&*jqv9mzA+kGncyLn)-yo9bl8O~Y(*Hjl+M_JS~*CEeg5&VF#F5Pz#9+m zht7FAZ8L%HPEJ57CmK)MhvBW`kiTw~(KE;9ClQxi7Z-Rq9L=i*9E@y>ZrenqeDL4I zR4FkcISG?E_MZXh{t!C!P{xO$=W+$R5e7c6e4pu+Hc$M075i(aQ*Uvjw;=NL4=_KW z66wRxEn*AEe_#Z%JQ`n%i zV+-1exG}8owRwMytR_myXIPx*42=hH+oMt1uHFk!9eVHuN*q|>t&dx)3bUx#fk1v; zT;uMdcLTcX*crown||1X3#7G0bxP}Xz#=*nnKuvc_}@chYen=Ovhd)Hhx56shWj&~ z4L{zLp%;~;cZsr_fj{~8N7B+2;Rn)a|`JZ|WM?-mBpF!AQX$1#;FB{h|0UxKn%3K#v?T+iu5J_U80?)bSHlrbRhWY3+$Q4 z%BWRzwE5d#?VVr!;~gu)J>OpVt^Pu5A2M(?oYf`_-M3fA`6-UEKAr9Q6su@p)xGl@ z8M(xin;X7t!@|G)@8!8i-o@XT8(639ct}v2{oV^*IHTqZu7b^MPBgI1rZa!y@L(TX zasKDeZ%9J4Fq}uzy)vajFqI0o%c2Kpg$egFPy9tj9rLoyS#My)(_qE#s`wVUP zy8r-1nzVN@qkVlnfa->XpbB)*+FD47_HD5CTWmEA9|bFwHTh%bm~zM#Yr}l|Ng$j+ zEVO#-ajiseeP#u0~JLbo4mW?Af0ZykpE17Z=bg^WcR{!%D*mwiM8GL@J zif@aKJDo_zZ_4JP0!hfVlkg+bVC(+?@Rd&!Rq@Za7TUy%*NMc@ba0fL&ArvrfoJo? z@FduicX{P~Pef?!UuCRR7R`dc2ul-S02vvEhv{#{j9KMzDd9HSK-DkizLa7~c>qev z32kX@`E_b_;+aN5g^;Y(4jvi)RN5&ID#ux1 zL`TU~BJ&dB+f%lOLUj}NzQ;pi)(jt#RK)NaFb;G5PJ||Kqtq&Wqs`fQ&+JAy-y(QU zP&nr%d}TW#=IZ2AP@L_?B_UPuy5iqZf>b_K8#x31GTxOEfOU2 zqIVfDQBd5-+J)fXg@-Q(`T@X9yV`k78LvujhF)En){g|JKgFnm>pNE+XQh|F(Gqx=qq$_uFV^U53U~W5a(o zvE{vAck!dH5yV zaMpInB+R|4du*)ek^r79bm38LdSauWS3U=_E|JhS0dU`V=;1OdY&lQ&FrTddnNLcY z^?55sPbA*g=@*Ka{S*lDSD9X@r)SZvZIJe)*Oz@#13b%iy?E#q;2m?R62nt5bQ8Wg z$)c2_1phEkTOBgHSDx9l;M+}&28qr;W=U@Dt&6TTPY|h92YAT`O-a!EAG|0-c(hetmz!0ApQ__Wj_XSS@a&idc#NJt$na zNs9V*EH9kUn)Y3_3FfsBY5ab{HTXJyYvoz$89$G65@Kn%S>ucp(OX1O>;bIwkSkwMIG@%OLOw% z`i0^2vqDmg!of_J?R$}%4L=&$qP*wDrw)x^gid<%8v&9Dk1`hGa?nR<(>wokiPsfz z!@@*iji|Qrjq8~qFx(xybSa6H-I<0q{0g6?6V+3pc=$>HV7Xp2E;FB^K?G}q&@1i< zh0|s0{f1FqJ)9q6t#`53DsXFrv)K5UN<&3Zl`2c7-0L{y(|0VKq5|S;A}|H8bDe9J zYQKZMBNt?&5~t4VuUNVAIAWr3H_V34RC0AU&xHL=9bI4fs5T`)aFO~3==rw&j^O*E zkyq?=#gRGUo0iN#mRm^}rJ@+SuV2B?$nTSizO3VkKEw|B`NSw)Gof9(nYY)4oY(u*28!DBe)OtRENZej=F!?uWNeo3PwZ*OV&qZ&gM<2m`8n zZ{@VCHYBEUHPO&x&J zVWs37aQVjiMr_@1TDR&tah(NTKCmzl@;>e5=;DPew}Dkk4zIrGv}cL2a}8q&V!Sv^8Ouw3%0$MX-DTpI$&6ez7nlJx@t~4*7L&R9-RnbU6Q=JTJu41w$ zEr+ikcx!FG=8G~#S6RT+y$(F>@+hs}o{|( zg{I8IzCK955cQ%wJ0Cl3O;1aQ*w3uSkKyC}9d;C2>DO!?iWpb$88l`!Wc#XW?acS* z9}kPg?qQ{m#LM;LXAhM$Ut>*CTZes2fzX7)1M`_`6h_N_%#q2Y2Y34t}`FDO??#KB$Q|mE9kStr#qi zxB0aJ@A3W-%f(X?GstnRc%{zzzAd)5ZE<3J!cF$`3|Le!1a8}zOl~?X8dFLxaDo^o%>K@nl;zohijU z;AH{!Tpl$ePiRB|%dDc~E4YVJ-+Rq&;tg=6drqgmu>$fcT#bRSQ+;hdBjYC~&PFWM zGWXr=1BC+L?ij;^8`&3POJXbrqRXf$jI3#%3HJCGCQCfcV^3tlQJ5K3i_*{TIn*$9 zk6~dLjVQ1J>KQ z`coBAHohxlX>M?!Ei#g)jFpuOCu_UAU>|iB*$h%MCU-;LC+0fS`REC$npg?q3zY#n zH=>s8=vjip)JlfRc`Jl$BH7Us0zrf5Oche7kPC;LUagCEBE|eXwxM>4puQiD*S}%A zTH|oKQu;uH^gy4)n{yK}Trqi;3Pq!Lu5My}wDe}e>P0tkek!(W?>z4AEr$EixWV;l zWyCTTCTp|88`~|e>ALjOPz^0nYocAIADC}T$O*{atl617#z$9#I1Iy4L5wd<=MG8s zNC)=0+$1~ROT^Rgpq^He0^F3l&O00ae;DhYhBJ9 zkzj9D&zSG@Hct>Eky87n_~Fy=A0+zeCc4m)6XumpQTY{Rq+H@W^{w)7?zCTJ z#(g0EY-pKD7E5}Uei|DU+RXl~uk#DlD?CC={DlQ+W88hk|4#B5uKdH<_lp;c*Y_Pg zud`7~vpZ<>ng~)1z5y=Ww&$Pu%-<*d%bIWOLHAxG3f(ZQ^;i>p8%CE1U}XT53a~}H zsRjfSPcZKp9!4EBf&2?XocnLrgG2jFjLKt{jJf};6-;X<>RU447#iC=Hky@Vz(rlS z0d(iWDOvsg9gE&Xysu0Ms?DP$EvrP$xuHxyb&h=jlo|7hL_B>tmDHxAgLyZVUZ*+9C|L=24mWuoe-NHweEAZ*izc!1VtD)f!Bo*X?`kd19_=E&t z6$@VBOhcWPr13&)cH2$0G|2-zy?`CIkTdhV0a>a&M~9Rj*kqj!Nl`6-*B(zAPmvDb zE*rdOc@zSH$SgNnI#sX+p$CfmGeHfD&e%Db)v=FT6313DMNWGhU&@%I*{7RK%7!*A z5`fW8`tApdguT;_);T-O{?YE;RO+DCGmiR8g_6vQWv+laiIlehzFB(Hm@k~~3Ki-y znm-eK6j^N>zYv<7mXrdc=f6#uV)}|GWWTbA_8O?jnsC3Pkz?wwy%AbMU9*3>`~Ieh zmr$}nmYALT8cg7g4znJBKJO*@^`vd=Q=+u3v#E-%%qzVjldoDZ*EomigxuXo@ZSyi zYdE4zou@CZt?tWc+oAu?VCLDT>%c%l0x~q=g~iwIN%_8uqV<$1`RG>I-w7e11W8R4 zBOR+^N(vR=M$~B{j}zQ)r6I6W{+%G}UkFG5JQlhZZKK|1Icw{iGeZMH3iLp*GDFJ6eJY!sU;{P~TZC5CBE;lEGygGYjDykaAs zM2Vjcy;vNIo*PdA&{hMOaHVg8Od*82-F@`EmIf<aA*by+>2 zW8eksE!m(ubluK218d&TQ7Pq&WKRcasP^s=kEXdndG1)D^3xfoEPEw^FC}FF6HlE* z#c;}!no;EO8>{~D+o5B?_oqE1CFU84EJ-trkjRW^f1t>uVC|cvTwQ*p$E8-b@?sde zISn?kGf!xsVkl4!O#M?MJB$uv zpSx`|T?{LcsvJ^3UrL$IA$w1+JjjtEu?Z`aZ4D%z1h&G;?Q8n0!?LfERn>%vnFk(9 zyaW2!jl-|zW!@)RZmC(AFD;+nKMnuLPFXaPDOnloMv9E`Q|qToE{r1O3h0A;Wy&TL z?W$}2CHktL6)R@THW~rgKke%_ali(G0+JV9rY-wG2Sd}to$sdL&=LZ1*G46vy`W>c zqiC|U(MHA@x}z7$ z$lrdk^mk0ZuH?_`VxEBs4zTsv&>xIJ;?pY@(*NPwDNSBhgWgbdH6tJPM-EjYzF=(b zvPVRa^6Z}<)UtTq8z-4CPcS-mSH`V$o$`66NJpBp5^`J1FzXX_5pu@8oaSetr~4bR zQ5l(Ddwm=mWqvJB@s&Kp&a{_r$Vp8@Uuy%c8(u}UuYH}9GL@bYwWGqg zsrS!ClnFgj#n8>y#+O}dEX57`DDVHqR zkVtGj%78H+r4bA9X~d&qS;Cd9rkriW^VPxP+~K>;ax_VbP@XQw-Qu3&=pt2;aCdi9 zYY@U}AwGVUN6)8GXETHko~!cnF$aq2onX&Pm0No#QRluaHcf{?V}9x~kowDdBv^8@ z)IGa?3YNbvH@Qpo`r*e{3%AP->o^;~ED1Htss(}-7roHFUhys;KIbmna{&Tya)DM& zv-(27n31W6`Xx4#@>J&3i+WLFA-=lv=rTpIW6XAQ!oA~lROkL5&Dbne&Ej#w_Fq)P z=-i*2M$#nVm)vG?Mo5EyTUf(rj>-5eHvtY@Ti(b~%8kVtI1+Xb0GzpUvr2bWnsjsk zx2P$pQ|ZIZo!ZPdLrd-CEd8DhhkkyCs)9Az=qVLFo|HqepW^Gs<)YJ>0bDo9+T;&I zS!P80oeFC!qy|;(*P-lMe}p!p>)GxysBu#zU){cNmabW$eq3%+v2u`vu@M<0|Mv*OheG*g7Q>&1VODCVp9Du0`-i z44xhB=TBcsA$Lbl?^OTIj$S*Bi#X>jMyMIog ziJ4Na%1Z?)IZ(LX@XAm;P9b(_R@LYbMFHbw{0BFA;ZAre(I7xBpP zgGb7hB=OT4Cdb0T-%u*`Fn)M=;n%S4e#~`hDoTAYM&s)M=_tn@n21nAcDC#Hg^zhC*NJBXyBIfggdmva5@*?w1r0S2-ATV&>DnZ7{~48u zb+9L61*K%U9Rb`}7_5PCQ)-_p9@Kz<^j#$0%|vG5>?>|(5n7cuWJIa*4LIs+#Ea@4 z52)U>E9R9AvXPPn$3wO<#?c)Sbvbu*opWzN>m)+g9_la`3C)>Z!j%_0SU@hGxD9Tk z275Vw(*z(-100(DD|2k(s(lk8p ze*o$~bIru`2VbvT&VOlGXyxyzYWxon#HiV-6_o$;ow7_k5H1BeJ}kT4V(ukI*qx|k z=w~;uTNpZ?eM{e1npP+g;JHZoL>N}IUeVeeYhi$JeqZzEzer4bdCd9O4ii&N>t!4C zEZ*S5Em^^-l#%x|gfxtbe0%VTQX|@pj2vDixkAs}j*Tip!b{RYP@vE{j{7UoM}W7* z>Y$g@%d#a&&(V*AgMXrnW+Kf^)aV$f!Iq#d{hZ zbGl+EWAbtdBeoXaV#hjRW)sYT>5(xDLEd-bvWHkwC&He}PAKD>(x~$&0Je->&y+0h zIDd-l>Pofh)%ZtoTybm^$+dzdU5)ebup7=tUQ|5LC-i=cxh|2Te*_$Abv!CG%ez$V zowz9<#5uZLLoyq`%r7uEduge_K@XsyH0M*qRBsRtOzRAzZLu|c&Ksk2Ke1kO5%XT@ zVd9kuHUK9Rpbz^;8bW%-OY^Z^{Ua9i!VqTfy9gq3x$~1P6xYL_NlCMeY)@4+(r)Y! zmdPRmmz72&r8z}H!`O)6QY~DfKZ@5VdC>e2KegFYM#DNes1-c^{nFuw zz0GBbVXWZ1#iK|h`nBf!AaBr1Xv2~pjk3=@`(mW`mY%8UR;-@EQc6GkEg@!=W;N&6 zoyjh;#2b5PwkvT{ za8rr*nVwG?ou@R7jhDTpxh_GrHI;J@+qmm1Ww=`OwmMC*7x>CRp02OgiH}79+FP(w z;uq56irt&w;SmzThNyGjaGlw!5BG41(e_<%ngFIkQxUegJ~n=?I9Bbv@DT-x%vN|+ zo#I-uVrAit4`xfY`?Lc*Z|&^!7*rQd=NhR3n36gC%Z4<4JqxCw+B*#zhWQJKI^WUO zMc2jbZ1?1=i{r}lLcx&Q;yuVlG+TFDKD>biP4b8tIsOnYwgSy~_SM8ifY+;Mm zOOA#(E>%OuiY_AO|16U?O`nPNxj(6WLrt6Y006VafZLA?A)tmwZc&K-`DpE$!LSf0 z-Lwu~tVLM;&z^zjoXYl8m2y&|`FlVVPVp1>G_fhVe&}#e%_n|fjbo>Tq1U{J6<}=3 zPwVq$uBlP|1K~*hFQFi!yl+L{S_+u`LL3T5RMC*0q2kA7Odo?zBM!kanwTtvV5V#9 zp?`*(mEA+?yeB2bEntIQwmKm<8@Q8(xSNXH0@~LR2bgg$5O`_x)J7iYwC(hLT3)0n z`H{B2vwajXKuVwc+Aifpey5Qv)4vLOXs@RgHG z4V4RQPUXSxKZ6z)Jsm9_D@$wE6SLXVJ8l}>SC{7`0|=g@)^d$WTUz)3?bwxoxe!p8 zDN?Z?(QAv zo!^9rbQ)?fb{Xgnyeti10aB7>qB(hyy=L0PiuQn=dT(GwW=CE~rVZcth?zWGApG5^ zs+EtxkG%iROBV{tkbW|_@hR?oMy-kj@nzeILc;ukMbs`SKI{RsWAaQBKEQDj=av9n zK8^W1=x%w?uVt4S*ax_T;fzw@jsSq{{%RiV^!}7Srz(d1hEq!Qt72DAM4OD=lq#rqrmu zkv(QseN!$=46UgVHCtc8v`FV;H`wlshOwAqWERMUyuvv&Uq35Nltx-m`)%jwLlqrE z=}&q;x@A|rY(i!*s)8Cno&E<$GPv3pRNYdc{RNPa7tT-jcgOw-U zd);b_P0gN+d}!wem7uy=ib(ZRMfx8*Q~WHlYK4!qS0`*OlhSz0)UYnjzlpg1h>=W@ zo95kSAqbGs2!KL|H!tn=jSnQ(xU=P@`om6glF1+08t?q2>DRqY1$d#w-ta#sq+D+r zl{s2@v_ypfACn2Qg)y|;4jnOH;S$>TK3rU^$)%dM*Rvq;qo7fFb0zn*t6XAQ<6TMd zr;>>Q^LopP;>+BIr^REJ;OM&0!2Z8d++@_e|KID`@8}J}X^h;_k@APIWps{(w}-s+ z_W2{@*`Um!O^-U0)8|ijuBoUxq$dpdAprZTk{Jc9opWz1lJ*cu=-8)ORb=R=go<@{D_2uf z-A|m#r2`iyhjl+Y4(e8!2{Zc>HaMq^VngI8wS~<55?jR8Noipk-v?9If{{W3^=}2} z1is8aEbt?BgBS*yB1V!KFv22BaA*WM9JJbKCPVgFc68DYGjl;v<(8($;!kWjeL@Ns z`d%%*C?9&XIM+RZq+3?i2#r&4+0StZdoi=s{9kKjg>KsK|9F?4C$xUO(yU!uj*p(G zfZQWoZusY9bp{_fmZw@1Qj`e`YpIX4UuGAIX6EXbI(@<#{cb0-NB>Jwsdm#5^4uA-xgD*=6-?xtLFMv+yElA3H|hj`O>- zSFD49>z@DB%CTlyA-Wqx2J{n(y-`XFU6nbV_-8>4C;ofhZFQr~J6T-)Dg!;|nl_|1 z%ogfjoJOnoc|4<=I`_8wz_#d@kwpH*SvVEOl)0j=Xw^Px!QOdb#Z3`|lV|XnnubsnAGw$h|auv znPJ5A%YICd@#~E{kpAvhw_Ac~yv-s#8ThE*%EcUacJ`WZsCrJ8WLg0f7>%)QBFwPu=@ZHQ>N3oHu}k4xZ5v`Ioiw_yyn_VMl?a znSPbSiOxjRP;o^TIfQz(%h-2jui@=$S>_|An(QK52f{4O#hOx5EK@@>?-zaY(V2io z7o2gc$Nb0>vQMMpqu2$&It?OA7`4{;obQM}zS&oVLjnd?S z?i=^C_DC^YZWRZL*HusX+F`EQZdUDH40m47{LxDCM!HKOXovQ8QHfX5|j4ZUsp2$BVulMrwAM!H@8i+O4&pTpcf_e%Zt*dM1Ct0}2zUH~o0F*ky zKlSl;7Cuv&LJ#EALwEym5?wA7eR;KY%v)rlphSjgHa+xDdALaSzG2Qsx65LG<6-uh zh+Mm9Nt6Zt54p@0;&BBUotwSri7Lk6#N5pKF2Ycp32T;j4}?H&CcS1){`8N^AbIXj zam9j$%?Fwmu^ieXS?T89{PVTTcTJ1>z4P-G_)ezHJv84@rYw4X1U70`wk(SEZn|-C ziFhhbahQqFd?dfu z1CPMRf6x9@xj##FT8Td)EOZAKyI=a*1+}aUkNt?6Uc3bdmUmQjqj!G!xBNbB%D`0c zRN`|cnRk3dxUJgx3Ywl?4$uD&pmiaqWpQ@&=!A$;V7V7Ez@utVM!*bG(OTRQH!rnVB!sR$LE9v!~kHU-JO%I3o`1^cBacLV8$NKUS05ND7LU zrTSNLsHh^DS_K2ShR@X@UR65tFWHf6V;V)m8P1HA&q-E(rnZ!H)O^;urqW!66^i`m zCf|)Osrst7Ve+)(5DNNIrbS)Z&&!=ZQ&qMBR7tAl7$zv@gEy>1;m^&HOEAahyuVTS zc((x#2SfcYT`OiU>NPtr3^NvHz!7pfHEV%w-n<(x8m@JZL)D_~c8}}wgPcV^FE;8f z-?NR@ykXdKDTUvV2FGiqO=4#kJv2pejHywjE>Xem1p#)wo?oT2l%D&xl4BMi5@D`? zC9@$<=d#MRB;$G@Vqkh??j6hGzJ_{YO1!d+eT_$XmIiJI<*FqJSK7A|F zmYh(M2+)mWs;^I%ZO8-__^|(k<%#iCH}UKUcIOEPus?Wp<=}IhF?^yP8LJj0y@Cj` zcF*zf{xU`Cd%S2DQfKhm?Yq>%^^2K4$wsJH%;(vSd^$DDF1o5URjtP-;_m)WEDZ*{ zjadZxqXL}%3u^N#bBP2ZOuV&OobzvOa@J`Z#A*0(StvSwn(aDCt==vAsHSCXr)m~>@vIZ@_|G>r>PG96pnMXw4u z0RC1m;|i{6Z_i5n2w(zGmgWH~oW$&%f+7ouD4X4N_C#=_*6kPMDS3{;cg4YzTh)J<^xoA{5}`Kar6FOYE#j4Ap+KhnJw+P1JTY7AC@q0RtU}u*GCUX37v?PVz~D1n zO3b}>IVm@xdo=@ZJt+Yc%uSDiPdsb=-kF)RV*S?ZO#UCoPMilM(Q4-!*fQ%}(aG}hpoS%4eXz!U- z_ThGV(7^NwnHGi{_eFQ?&{00!gU4kUs*pF@1hpnGmz!5n01wD#VHnttg{Tcg(Q2pr z8K6<+X8TLuNO;@*?YW1b2JYW|s0JHd01aWeGDY>?z(A&&{KmKCd@j)*E0dS)i2(91 zF;~Q4K!+RxDnPv|^X#Z;&V}~-W(bQb@!Z!-)lG#(LK^@OqMcjInv@=urJ0wp3GG~Y ziZBW3qVi<;|ICiJX3T&B>rX|pa0PMAaNN(x?Urx$xtaFW9|Ne4kLJ`)6h`wOxorO* zOSQ&8OQweAzMo)KXel~YoA0rb&yP#gs_K5SSNyMY zsH|UHqNEiV9yDp1aH{r{(LTjWgZ3V)rBzU?Z}_}WBm;nEn`+7VD%T`a;j5q)W5FV(NW;(=cpnH%)pJ@%PDx;r&hbWd{2C81Q%Sy5n!_s-rgu>>3Dm z?O0zIu@S=vB;ZN`uPRV%LJoR;E^#sOxq%~bj{MYI60QNxkHbFQnELnBUdU=z>axDF zp7yQgn+JJz+`pUGYQSm1zn4O-%iW%xpR_Q%cgX(6iT(T0#AmIBieE>9OeB741e-q7 zW{o$+Ov<5@_4&&K$<;SM5a_1s-Ff>MKU;_IjXUL(Y%xx5^<)=XOrNgRAHw4R!@#Q8 z)LCVa!h5>&X-R9q1g}ELBB8NBng9tGn0lOqn+2c&ZFHyxm3QIaKL>R4dHoTO<}B&i z;4wmJS#rF$dg5fT{;pDf{re$5=@=1w&Tu3pvj7S)!h4>3oFKD%Gtt+UpV82peh-0O?#eg4g5i$OLj+%rzIV#~1;7fphqi&{?f z-5U+76*0jfv)XREl%}?d1$W)Ryj=(96Ka?l`+7UNHu_$Xu*9*b4($9)`kR)rS7*m+ zoL=J^SSX`yy=oBxz)@UvS{gcNSx#RebIDr*?qs2)!-h~V1P*}U;L0!yj=ljVJzS29 zt{U3sZI$8rInZzG_cO#%?zkJ7=AZf&QtB#2cGkR+q>Hdf3Lwyen<6R5oCt<@h5O^N zpr=!b%C_rJ$&bkua^PpfuOGWFU9oF>IgGNYLN=9I9uwrIfK z5vwpUl%71huX1MmV7x!(o>QI9aGX;e02!SBNVit)h5_)9 zN|@3D`7m2YfW(MSEqysTyIS5IwL@vw4%!E3VNFpe?E?x9T#5M@-(e};l8oksOC)xx*>KgJ^y40N z7en|%eQ_lI1TPBu@axCM#%uYz&&B(f>=YAh!~Jz0`pHJ#5r9Y)c!K3I14-ik#-<8Y zDLqd>8unJS`RRZfSu~)6CxW25Sf&6J<8alHF%>hRVfjLrT;}`T#LN*~R+?3TKSkpK zGgZZZWZgIFZ2~bjf~P}J5YqzCngzh3chx}Bf> zDsO*u&Tmn_KI8Qt?>**g+15fK$@}K(`nNIi`jm%%rpqj2d_bYZyp8Nh2aZe`lzD)+ z=C9tj=kSVuzMy%+pXokdLw?KX;HeZWcXM~Ts#EW^AfRDukVI#K?qZsz&lCVp%ZJ`} z3^Mu#Q&I!jaiWG+^%xGsxW>u%9R&)Gt7g~BQ4ksgrGa)cI+ehm)0hfNvDFy`fh_=l z;JhfV*~v~o(|E9|V}RvL#9MiJ!BI$rm#J_`FPi%4wap(?^Dk9NfuHi?v0xIZ_Scz_ zZ%dU*IR8u*_UTHyuHts#4UhG*yEQJ%*)B*|xwMJtdj8CyZ2I!m`3VQb1y}QlqNvEO z;5q4YCdvJNY>;*TBQhNGhSYHS@6D%VZquAITmO;O`1Vjei#KHjuXRlc<^eFfME4Z{ zYN(ny&yAdE97sw%rRm>OL#l!Dq43W1$QU_L0Lq?gO~h(xbOBy&2&0@`G8Mf66Kwj} z?0+qTxW&vSo;2dt zPx}QMGbYKkOmIOeee*}@+tvm8#-#P;<))y3lW10T{7}@Fg!YRP(ayqw3)eq1+SaC$ z(FK>ML!DuUF4o0}sdJm__bpg77x}}!1>SmCd-9qgrqTAHiObZ5$3+psLMH9{3~Amx zGhcwR>{}Ze7;rwF6MN$Pfn49%I7u6czy%6c9E#fuw%}kan5%`Bmw2QJ$W*X^{KU9` z>NlO^_R#NV20BPJd~O)oE7FnCr|^-c=lZ1yObbi}6ab|~yYS%oMnMZuvlu6EBy>`vB zV`r^yo$n2c{XXMWveek70_C~ajN0RirO3E|H~fhZu3|{mBjPXKtNoGlQrmm@jzL1^ zNcMIo(|EfYh#N-dBR5$Qzb{z4@^pZJH%?Yi5hCpHuKKxv-=!=73GTu-tw9RJ!*Kgq zH#Vh;Fy404(DPX6uKUCPYaIk?ZjnJ`3dYtY>mSy#mb|cp0;+pK8X7{?GBff_tgO(F zEUO_$Um`cu^1t@Y9=%WaCHub@-@Z;T@7L4(mVCc`R@^_^9%>UE&^G5Ife7^*=@h7R zErn5){bG8+wY}=3n?HTk*IP8c zMnVeI|Iu8cb-#UEzsdhv1<<_8X3KR52^}k?Db1)n0RV*;c>@9n$`qCPaLV+dY+8SP zVOLCtd9`k7zvEPM@272o%|y=bBu?98Z;$tR{|B3IYejP3F@=r5V2k_HDk$S^+z>WY zFZxmK@{Bc=etqnZcFU-bC)_-?B5m#uroT(j{L%48?p(iYwr#d0;6b*Rk6CKu0V=kB zl3S-GNGs^>z-JpIbt+>!|3giW6 z4I-PpYTokV$hFkJmLrYno7H;wP#N&=Vca*^4yC1ZXgURi5?#`K27 z2yeQ;e}7|W%JRyJu7{2}N##f{8WCt@)*W-zqk(b~q%=@60XvJi6p&?(0&Fk*abKR)*;B{HK+@Rek7p(J65)W-ZP&lf8K)du6``RqzOXGc^`yX;bS=D7!z0TNZ)%(j z9m_nt@Z*lDw&oh?>7UCxWlrVQ&f61oIfd1$?o94)9?~_5UcgohZyHOO8?E_`vWM9E3=fKhO+-sZzp3LBH7Wp>jqceEPBhU^!j zlAoWlymZFu#kTSP0S<1Q%aISbKQ`Ri{8G_SBhDj9WPNg7Z=pfchtnnN6`==qODk5C zY|1dU8L0)`b1+m0*Uqghtw$a8 zG(4++S0~_^ll6a{zK*x0l{L0UV*XSd&3oG6aK0)wFd!q$HOz(YFIABOOZw)fNT&wr z%A46mVd-{;12dEN6t|+dou^h^XB36LP4xqA?w0Mcp>L?8V4!6qqD2b@}15i)?FBRo3R$80)&N{sgX8K7n z;-(zCiYvRPvL75`TMh&S1Ye&cNZ2~kjnoB?9ubFc|Hc?H5w@LxYr+9wO;T`{ zAtJE0xk_pfzNCrfpr6C27u6xPSdzzyfm=&vY8_zs; zedOxjAxUggQ34GBV$4Su4sfW~seM}7HlS6QB6oqQNDn7(3v+a(Kr7R|%CAN5jX3J* z>dNr*`7}L!k$1xBklnZ1kC)fwR(m-}x)9_&9F zRMK*QVXP5$`s!7ij!m`dymmaXEqQSQE^6tB?aY&ojV)jQ{E(~VupNXn%mrrI;liY* z8rdGkg7~V>e%}^17O|Tsi}Zme+H-cqsZNfP06;^4#)voo#>=cmvAyg%{Em9Wi))nL zM<3l^wI5Yq1i!<)n8U#$1fj3=pFGeQvcLibRGoA!77POA85>~6E&Uz}#s|s=5B_=o zM^pRypB=yc*_}S^eBs&S+t>bBIQ(J=A3vM$HrTH?US`jx02-HKPk5krt?%@{=|dk7 zAk(E`=%%uBqXV>*%SOM^Z=TDxFlfQA;p#KkL;L9@HvQg|mDKkBL@5I_jD*l5w> z*!uc6|H0XT2I-c7#Sy{s7KVURF-@&A(rgW{;($tc@{w$H7LZxx{<>F>*odikuIm|R zKO1~!GtN%oQS*KGTLrK}z&IP!`S&+@>9U3~1qDU1s5Zt3u-Ega9Zz#3O`D8aYcD@! zuZ=WiR%#!~|M{19zelJa{_RNV0(G!TGW1atIuf0_GC+d>1YS)nV^OoFs-d0q!uEEj zaMf10sXU7GEcvt{v7z%}m6z*^iMs_{) zOhQ)Lp)qnO8=;+mU} z2Eiep=+hTcPpyWW&PsUY84(%4xGwBD?<`Nt>=B(j!_;MCotHias#mB=(%k72-ZPj> z=#sR$hLg+HXIf~VZ#T8XJ1oajXL375Y<=4kTpglxjFEa$Gu%cQ@p2GMD+sJCjlN+F zD%z$?;X#QGe2tFN328EJ71HlH(9H?p2N`sE=uB9lj`>v88v%<(rlSQ_1?ao<1PBUH zjWo}nwX?6Rjt*L5zN)nKa47rb>Ob4W9SrX}$q7X#e(qV+x!B$un+@qOHcf5FQX-M; zS^nw2TYQfD>DLFuC-+QtB)&brOBS={>XumRx;=0zrlo%}Vh5e{^_#k$i%V+!8BY?K zTc@V(4hgboBo3Rd7`xi0YxgZtW>5dICvC$dfO_AhE#xFRb@NtyJHD7YSjQ*; z9Fvl`k59<|ld$o!Pz(QzZaZmsUOHYFbo-J^?Ii+#ocO3J{HDyd@}db?o5)Um`{2Ws zPb#RXL>V7V*Q&Q4dqGFzvOJg}6PVZj$IC^-Da}q( zm7h4^odMA?&ioF}P%a(de3en^EyKO~*F||v2eYJygTMIWxo{svxl!DQ!DIJjsZ^| z4k$@u)7Qei)x44XQd03SM;v<0^v^FpI69mz@1mL8mddgxwRX)&c890x1Qd}TpH6RK z40kw4_^Q4MH+U~ZoXNTQ(mr68lW5~wO<#F3b$w}0-~UYDdRvB}5x!j;Q`|mq%woZP zRBSncnv5a}jQR*5t_C2fv0=Th))P4s$=FhJxmT6(nZO>tITR2BXpch%27Dz?6iLM_ z(&}}PE*4teLdZ?P)X>3eSJ}gaB_ttN5c?3~zPjh?1;_fGJKBxhms3?df&5wg#KU`m z8!eQAtcf!|{K=ZVhp+$b?Ik33@Mrg$56b@fLt69Ebv4E?znVc+QwwRCU|v0Ly07`s z?e0is075n=OC}Kvw7lWnjPjsk_OrCI%@Tjq!}%63%RiJCw|F=vulUDGNks-MtsNiM zDpGY&t}QfMdo}`xU4{r?EL5}Y@vLc4eY>4!2?`z2B>{ypH8o#^asYt@l9@BJz3I`;>Zqc6YN@k!_0M*nc2}QHK{8PuXBs6<+$_=h zai_VR%s}bLgq1~VunhfS$!eWkv8K5x!< zq`Mn$JsSgEQS68+xf7sEzoNlmQ;;AhXBbNa%*?Rdt;hSsBe`18V>3{ik@?dS%hGvulE_rEtZjQH1 zKE>NQs74N8cXLJTeLt5oTI;)WN?p%AP_ugGIg)lDT9O(|;PS9HyK6M8Y@b~W2^dde zOt6Sug*zz(k64b~w2#%G*|Spn#K5Fox_A`daWYZ$gB^7e;Qm_#I-4rGFSISC+E z7_d}BhGecB=SnH!8ll>Bvauv22NaaUBk7q%&idYj9G#N?-2HSUf5SZE+Qs;)wrKl^z<5S8h#;g*UXG0@VIutVcAPip35RrpPvgA82SlcXyxpv zI?!Jz&LcF~Bcy_b&=7i=4m2qVW$ORq7vtXj*RC}>T<3?U1XWv3UPE7(DS`**GPrZ( z78a5Zy&_c?B=NzXiUyt`ig#=T1N0bG47z)yE1=^XTeJoQMa#cu8X9k!XyOA_5@=e_ zWrir3DJaHZ=voDIb#DN%43;#g9bgrf<_Ey#mmGYq6@U7n;6s(;gs!x=viQbP{X_L` z9dWI!+;;0Z4U(-0n_k1Q>bcvn+3$$Tw||?@i(5~HhnFAqEJ)W;bXc+vOds4-=eM=i z7$iH1XB?%4S0f4hF_k^jHxp+YYF(+A-pcEV{IcHQH<{-v*N^R&lO`nm_jS6yaA)k8 z8q*hVDKPh8qd$P&dl5wxVgbOI3W;t7tCOIYL;e^5=E6uU5RYg`NnoH;DR}SG0nBGN zojRH~4vcl6wid{rhaynvh$_IWzkL6TBSuOC!zVvI3N<}^@_kol)r6(b%*t`AMH~lWo z2X-d9016QXU|^WBqeq_qvgcXt!f&=yXWUm$|1@{`XrN8ggY^w*)=JC-A6UeM0y_%h zL-tmsEH>SZoRDUgFutujsBbLIM~to>i*(EReO0yNF;m;D3V6UN4ryU}XvhLGsDc7n zP*vb&cF%qLR{mQTa{p!f&~?w9&D=V209m{^Mo6L>a5J!ND?5p#we4zonM?w_09Jq)&D4Ma0~~ty483Q)fPkn6ilDv#7_I;fs2O-2zat%4 z09gnQYky^^dQT{_4lKSOH8uE>_?D5NVI!%K42T76F1%sPNNTx{ADzA~s}KDnVq9#y zjm{Ij&hNYuap0u>P9Emg+S?4O#FQ^;@=@4-^iE-@^1AESe~)#HFld>r)m!hH_EwNS ze7ItANwX$#CY8&sGb|aAp(GNVUTnAEL)+u1KGtkG>z+Od2G{7zq-$oODW;>jY9#q= zxf=z)x)2N=6~%Yi3tZnLeJv#$gtv6d9kt-%Z_JTJ^CDnkr>bu1tV8RuD zFRsl+2hfu{Q8v9zhv6UEa=N8VqP1nkFf;;dYC#zW(`7US@BuS@2)Ls(T+KZFpDnB8 zbFxnhA+rfn>G2Tt{J{oapM_@6ZbL)xfw=^zLpuZ=n)hmJ9IM7;DR=WXf3n79cQ#Y+ ziQD(voeA7HIaWAscnD74xB6zKyGFWa+bjD2>^Vxkp(`c3M(lK=QRK_ zt3Iz_H~x4ZGN(PQ%M5be5*(jm8Fho5dS$QxG7=YRWSpxXMmp1p@7QNGKeTs82p`*L zT6!ot*s|}vjeo;+D#Ufx2 zwE%!>$zp_h+{3MN`9+X4kcg%;332A9*Z8aJxpBOq;D~`Kfdat5ZiDd7|GIdKi9gNK z4St#a@6KaKj_q+tIq%Ni8BoUFQO=}CJuRL4F~%I4&|xGnV+fkWlY>zTr`MCeo%~~1 zmFrS~TT@FJN<4dJEiO{u>1D^_A2ZWdp`k9T0wcg^OJ z70bkL2eoPD;X|WYi8+WcuQ<}xP>LArJ@c{(zumJzmlSMcK5ImXg-=RnE17QC5itM^ z18O?MnK|02I=T7)Q~)2^6EZx^6@=Pf_F#ftcMb{zH7x+!Ctw~0>Sup932obfo`|9U zHhl1KCoiAzu-#{F?4$uXv(a;j8L^i+;6B#YH`;pH3yb4e*tRfx<*q>$34eZQHYZm< zV700CHJ(3r?%&BuUKt&<)sn3&5~h|6D~UJMvhL1I)cDPl?FbU2%3{Fg7$#@Z_{M} z(Zk5v0RSYJ`9|cXQRpminnTjtkp+HN`Dx z-KVAg`I81izQcyj`fh9sZ3B3op0zaZgRZ-h?P^g6%284c`|#EM66`P*vZI#&p4xU_xw<{O#) zPaT^n<5z$FNZ$QZ*i2v5Y^?HrK+SbOucx2Ob=~w#>btN6h&H!Q$W^e0>xtdq=gyd< z1a8ds-mTz1l%f&Cbj@CSxHbMkD~wMDuxpqmi~tO_I2Hkj!DLGS1Qd~tpD$`c{Jib? z#vgq4^?|lVYJw=MNH*w!>N>x84|Mvh3Ui(L)Q{&rBusTdlD6Llr&?3LG~C>%?*IF@ z?1`rb-Y$qwzL&@SIL&xDAU^o1`ToXy_jE&!f4%LMg~$VU_4m0hUGs=dhS8L9qQtC) zga4HGyWcJ}cL2HE2Vz6wUQs$Ol|Ug~9E99>-9=$S&wOFe3HKnuSOBqUtSLWqQ(QqB z5yC5wZdm!^dfyT|J>kx-xnIG(*TcqfD-G>5`Mdf{OeZWFVwwpc3jjbHbo@ZGKNx$V zrfdV?h}tL8^v~SaV{-vo)SMQxIW;3ykaG5(8y*MIAmH@_k!zL8@Duhu&1)v1CfBSt zHza0@ASJMv?VRnj-6akp>4-mm z!$k;iQp8sd7NEA7@zx4r5Ec@Ay(*~`T(!1d01&iXDd6l74Ks`&g0|Fw#}(t9!HGEn z|3p6fthnhx?2u+5!3UQTm8zji=ujBKys&8kvS)cMGoV{F-#boz7r5RPrmA`XgSYy=Sv7ifbc z--E3WA-Kw^FHM@6NPuk?FI^H0)1_#DRZs+A!0Q)dfdFvZEk$6B0cpx*V}90nzVZ6T zUP`ed$<@6sXi%cPwWHqlItv&f0Pv?(2Y_k2;Q7Qv;xQjHe%th}KNUX05dTz{-qqiq z&GhQ8(L)1EgQg^EsVmCLf*2ydVZY}K}_0Pf`=ob|TL1-RhfZhH$01G>B;V z`=FnCC}t&B;0BQr^i0IaB#H{;UIBHGE^QjS(KDzn+WaxvD+zr%7_rtp0PE;?Kd)9ud0`4_bX614O^-U~s% zm)$hFOqZJbhk4kla|Hwhpq?gxg;(>%XqIN08iA5&q?t9z!f9Cr-Md7_RsiW&)CcJH z$UJZGc=e^N{?^&a#?Vv7lEl@{+KLBFagk+J@wEpp{_E)zy4exb zP#k-yzXMf?9n*XCYc|MUKBfDP8!)<}O0is5m1%Vv9!yZgjq45G%(2z=?3vX*aq-lz zG4=qA6HBIy4f6yIZEn0YL7G60wknhr-ir2w#2}VzvM?mGZH0cw_MYWBUTxbh&F3R&;+r0ED_{Tm8{|2(F!N5A zH*Y8Q2Um8vUhZJYB%^mxF#Ko3xqx^8|eA*lC!9U5))%cqgbJ6%mkM`oo2^C;; zBp7Tl0~{&ij2v~A99;WK#zMK8-C_;DSm^;n4MA4g8V?s)oxN2_IT>LADGKv7#yahTaGSFm9RA5V=; znwtzgRaISBc<3TApQ#mdr>~y&StWh{x(+~s(3C=#%q4}w7h9l!RukD zF{d2@FYR>-d8%xez*VL7sV%j^XSmy?7gjJG*C%Yp>-CyEfLTcWEDb=sEx0CPC8j*_1>42NlL_2Lij z8WUP#;oXCAk*9!Fa%OuMc)O=+53$S0f8MT%eR9WsNSf(#tF>~HA(^b=yWGy0R#(agi?nCc z33l^?ssFh@mtjJ9T%BKi>zV7#{(D*k0D}g9)+REb4iVT^x`|2P&OEB$5{{RanI8(I zsn@8p6rRILD4jgCd_oL>qbyvoRh4d_;SdRCrUsBEBu2{!96^W6AQ>QT0^T@am<3!N zzrc8EIpLYLw|Rh-?hO$;&F5^tar#j-zyEP|c5w?m zJCKkqG23_gm#A9{m3Uty2299+xT7(U?hMSNMWmw}+(-@X&C!n z@IwJ!P7bzubRht^OAw1-190Ffy>TUeB2e<$26SAu4k5tXK zqAWMYL+{wP+460K`M;7*RSXRbrM!)mHr$Ao#-QRwwVOLi#=a~cohC1Mj-8tt+8L)~ zb50r3Bd$ej*ZklVVI?nsxq_-V(C}C_0BjGMuUFWvpfPDMEfHXktr`7$HAlxB{!jvs z@6~rX5#{@M$jd_wJX1^-2|&Y%<&FH|7LLFgx7x>IbJq z?&{0bsbpg%R}llSe9EfS<>r3wi_-PUU*`V$W&d=0d-_k~;xd|J%MnD4Zg@GeDK?mP ze|^W`6C$Mha`1CdH*4)e^L$nO+@N`7MW9GyGWYm3{9wD8s{c&qx!?Pi@9YciP=j1^ zn&CG5^$n@ll(<2A^}9JAg2SMMT3CDIVj5luyC7bHMam#JN*k0ecrVGV`m)VY9g^=| z0pEC9k+qdx=5!p(q1OW!Xks>^-2Q+c%Tn1w1`>dU@^P%iza3Fx$mv z+d}R)U+Ay<^~=My+De@!9GsNfKB9x9A$)zeEq?y7UEP8!FA!jc3;W0mgEODLS~i5R z*@k*|`uU5)Jo9fYmFl}2I2;I6msrOFz+%dIke>#janiuGpMX{YnAE`+K@0*k5P%^7 z=s%ZN2UmYN9NS8ViTflvG6QT;s>ZEumv&UiK3|NuR#W?Ba5~*wjVE14rFgTbSEld;`E?hR9+Hy>Q?2-)9zf!dY5~K z-uUB4R>J0Cn~FEht}{-q+OG7nBfpf7mj%>eiTMH!R>{3IV+^`vs^?Nmzv5-09|gwY z71da}pgN1FQM8eOe$&Zb_&-Mvp%z zY@JahM`;J#8E1TqBmQK4-qu2PeuKjd;Z>8wNvxMvc3IN3XJ9MU;5O&8m8#$R=^a$e zp8c-5ap#<$m9Csl?hqy*F}Sdfg;NQ?Lo7Im#l-{d2-4#EJsgl$SLuORcqrR%)TM4< zp{`{uP(P{Lor|um^97*pgW&xVfcWYVU+m@KJEDcg0N?}&Q2_E4SfuY{od5HH4}Oln zo$7S|+>0lD>%5L)`$bZfv3>Frg`J?^<-p|PuO}?F9Mhkml7jW4tLf8>nM|)M^BXyg zOl5KgcO@?}>+iOxU#Cy67zB&g)>`0>?nRN854I{BL%-ScvK}@&b}Xr77tkvEcYL03 zwtexT*3feq1z?QwzY#~0J6TjJR)_3HU5?9*bmn>iMgsi3Azh}&{b4NGpswjM3&5_l zIo@ivTA4L~2+}PpK#QOj@Y7YHnl1!*1r)%@O^Y}&+7Oh~I6W3jD84%j;D_Q13qOZC zd7q5lAxKPdP3Y5Rw4RGt@0+q#o}(Jx%W+E}Lt0NnA*t;llKUl6-r1l_A=V{nil)Hj z_(*uzER77(Z&LhLuBL>UgjMy}PVQRHBRhBYw@ZrrEElzK>L*uL4Jx9=|M)BK=^M?u z=Li5vwZ#cai5XY00yCQp_TdgNT`9mYoaSEjDB05tjZtb##3+zMQZjPLA-f{CTMCRC zJ>X#F1ULyewBJ>dL5O48QUD56N3e(k;GkOsZ{Bwg0sK(%&*~Y+)0XX4^=<4OeOkF; zWxUA)!%_=P{44-EB11wEGvryYx1&K&hpPu30o@Sb@Z zRw)Yp!jJbRZMx0nX5q(@(O0HLJ8z1=y=_cM3=D6OjKWS}-!abL_UQl5!kN-R+d(x8 zEX=c9sBhKoov7u{A}M2%5ZN5DDm^Avit`>jIUafMZIL7vC51_Pn4pZt9d+-gV@|^= zDN#_=u%jab0Nhxx!GUJd8)$^MKn^~jCd4Q(jKLuQ0{E7|Kn46}{q?_{r}IPKJbnqe z;q*NqW2@Ges_z7Mo3DrM4a5}3v|bihKG*&21j*5Un+Id{K+$^_yX5y>4Xv=yO-aKI z>*QCjXIB}WlgB%j%tDoZ#f6?pE+x9Dp{J(4&CTV}8eYW&L>tgQe>^z1FkBuj8oV&G zcuBiarz&AtvI?RF|Co64Ym#~PM&j}B5tPdqdr}Gf%}Yh(|qtWX=r!k{C`s@ zVS|O&HzOw9)~B(zZwI8!ln`3H3^?I+Y;GE*d4K~q)pV+sJqv_tLxhZ0gYG<#IFPrE zm;Ex=fCCXU&yYq01XEs)`e5psPNZ!XNe+M&6u}GOBgWw@Ky)t?#L565{!TV2BRfoKj0~WReB9bC z9>>-_lc)yj+C~{kzn$K=vqEyDWH@+LH-_TpH8+(3OYZHK0*nz3m~uSLO`hKAa%I`< z2}4kz|L51(@vh-Rnx>OD}2Ep;XG2h`jumTK!82I;^2l#2|u6EX_7I=G-l3tE# zEfQFmcU53l1IYZAw?Ck~Lro*KImSCx(PpCRZ6Dj@3vd3_B40ljmM^l8srlYpw2qyV z4xee^8d!FQuR7I`Q%QJ`LGFw(gC_rHSlM{K^hCf!xS(hQC^2rm**HrjmpQ{_{??>y@+);Y%(lVfsrf z`t;8Xk!#|e_&GHxPv6_tUMfTSHQ7|ZEafgllzMb8Gmf%wX*bQgrUwrj-u(8THlEi4 z`4Rt3R=jik2xwK;$Zzh~?w ze>|)CILX;?g;mA+Xj23b!GyQv>s8enf>QeQ$Nrm@)PAj;J9*U0((Z#nsu>skUONwZ zPPdn1KrF4f_TMsd*cm5^{J%w8hM_B8r zRF%A{XNJ;-`tljp&KrXEAkB22_FJsFK~DRvj{_9mQ+iLt`kJUqcYZAMk)kq3y2mcKahix309ZSr-K@(=N=vGzwqx_>$yW1tM_5YEFq?(QJuxHy~YM&mCSZ1 zv6LbzM6fb6oTn0_J+>Y)=g(KsN#GdshyZo?_ARF$C5T~wWk1YXB7_n&_)WEa=3c&| znQ8I@)8_1w=vYzgm9-@Q)W927jaJQ6@Tsx@Vf&U$;n9(lr2_&h|;=1^lwsO&s<0S}}gbuSz&@*D?lPu(sWe4FL-4 z86qmUU>9L(0qiDk%%2?$^FzH22UuwU$jvg^;8)*zDV7fd2pB|`T_uA&6`r92-rYG+ z#At!3z^k(92S$bU#GH!T25R<(2h>Bsp8)=I$mf40pX4U2NxTl2reH0Tw9WIGX1b5Y z2QD6tl~>F!(P^ud;=CyzL;DtWY1^Zy^++{^I$soySV1o`=WaKJTFvR(%aW0EsD5!( z+-n$vTPYGo&ae&YwH6DEwAfce6Mb3{__WM*w88x7>cQ0itj>O>n3Ay?c_`b;QYPvB z@aMc!GPiJ@?Ct)OOA03*+0aQ{4!{8c0u8|PYbRg7#CHMTonL-#+cqb^EX zx*3#$1IllBxHF%2NR^kiS9_i_h5rAO^0^y!@1B)THh7gsYt)}pli%R0j_utsv`I9( z)gdpkOSF)! z_0`0(SsNwMRl+}}C=>v|9kKcPbo^Y1ZnS@nF^D^vLb|-oH;(V*-~5a84u!jtj1I%T zKEGaOyDzsY=Na`u)b-hqPHm7<@eT8dW5<7B3^}h(x97IceySZ3jJ0MN*lre@GH0CT zo28vK0BOk-5bPu^2%tsHRGNobz@wx(+5s|hM3Bv-r_tcl9sMGy63BWJgHXC+kX4G^ zKTlOOt=EvXIUs2T#KQoc7RB0=A3sYM&8xt_j#0<=4Mt|AHTwb}$PB$xVG6^l8#-Pz zeOl@UsWWjBzBC1U1#rmMl&LRMON5&3!pSTsoArc}>D&Ulzx-0GFKK$UMj4fJnKy$| zRMx2UD(g9`*3xs)4W;`Vy}f+(-@OL8LhIjBmRGAbEk6dodOMFFskhUBbLztOJf-0tj$)I}P08SiZ+zIt+RMhixGz$I2OFOTi>y7$NX<;@L(( z)6%D|-}_TVwpBuPk85ia%UDGiK(KA{pv{wk)yHM`w%ZEeV~?$$xIUVTaRdXL^RE-T zs~87Y*;IFXCkfBYbuAJ7pv1c|a`cY($C;CF(gFvgd?&hZ=Sh`bmm53y*Z-rW)=LW{ zs=NG}$+8exKw+?=fWNdI-z29-d8b1I1Qk8=!%x>=Fdu=N9Aa}m&*j97-6_y#9HRz6 zV>2D?n#S@#-b(XMzk%)+hU#9oKtKVDT^tI#b8bnx>m+Fu245ULo?0v#pvzUDQphj` z`6?8rPQi}4b=Zv$G+oi-TVh@XxjR0}H88~hTVDUXm**VTn=X#>bETx;F^X?5#n2TE zXD7)0ZBrV2p?E^)CX4Ky#iQ%??}NVGJLKYaF1mVS+k8=;{_fr!={Tda0tNs( z@xMZB2?p?(1D#{tgNDx7w7mx=X9;($*1=ry>f{BR=B5}gixNSJksA5J(!7W;ZuOQ? zGJp2rnO2JLXA6CScW6lEUfle<<3#lkMVsjaHQIU6YIi$vZPE6dj5K#w;o8?`)h3pY z`PaGCr)iYyE2|Tq#dl%v5i--j{*jukri5s*gjwM2Ec9@m@^<2J=QYN-10NQU- zO^+j|kJe^zL#_JO6Z5NxGrS^rXBhhA=g2BBULCRik1X$n@Wp&YT`V|K6CU^ z+~H&Z-~9Zi&G~VJ2L!rwG`C7=PSy>!myV?g zjDJk6CtR{OuF>f~e)$L5?^5ZSp+GA=*u`$IBViag`nq;!+%nJD#mu%9(z;vJ6+>GyV ze%x-~c9R{09e1IOIq>8Wad8%xf{6nRKP_*3mVj0Xl<4a{nfs^+>^OGVzhC%3=n{oY(EcM&^-h&BKrYu#z zi1)6bPNHGO0U%cY89F8O^9ZokZV*++w*=ii&y_n;%$%Iv51~x1Sy3p+e|qnHNL}?L zy81QYfoAjVDM?N*9g;jFq82; z=S8=7Cg?3y1{BDtEg>CddO#KwuA|{5t$?vcwo#>}u`%E_5wHud0W-jkna3(t#ODgj z51Sy~SMF`ziM#V5ba4@ow^Y7E4YI#wuW$UZ>tj+F+@cLUXSH2xP zvdRvS)W=JCbv9q$-YEX<`m^}Ff}+KWOuvp9cSV?faW zUG(8!M9wo5(y39bj0^0^ET;)!)ux4Wssj zFyfwO%0b4}Ft{{?Ml;aga`ECfcLp}nk}0dJ9HI*iNu+lym{vtM$oO`b+U}#H^J~~w zenDtR!>LMrX5Uz&m2$4H=*Q6G=B{pl z7JkK|qH^|%#Wb3nG^<{?5b(#re{YEYI7kZ$y>(_#y}CYr?Q7{fP*q;6jAb_1v=Orz zS*R5PA~Q=#7X~=8jLHL17E=M>{-M&Q=VA%H&+$~y`-PKhVsrabOK)!?r`q5?5zdiF zfdN2A(&vxO9&DGe7Ku0qS!-m>0|@|PF}R3Q8l+^{?RNg{w(6Hw=EgO%#`}EcdujDD zt^g>4m}aIm>6iq^7tj9m$2Thrb?GQs0!PvAj|mf|MdpyNXRbUWm^RZ|>MRNax=@+S zV2-}9x93XKSuPXlo0ijnP?gX;X1BUzzLkXU2sOBT#PJtJ(od(ut|zmzq>oKnelS_v zmoXFkR$SVudMrf|XZ&jBOc&F1G}K7uhY)fmQ>U5sM(l#}$`z77vu8SYolo75oc~g4 z7j@w1aca~Y4fm_JG}j9Y*vtPPN9P{TbpQYV_htzpMm48GBSUhWoNCU@A?8f9$SJ3* z3|Vm@iE=jQLynU<Y$X<4;#M8K>1aUMg$X zHvP%nArTP~7wzad71Q#0GkDFxWjX55F}(=1lR&bAFqGF)`uYm-ZlFWhmEbL}#$?u< z^($<8z?%Eysq3S}tju+UIZ|UaOD8wl=Bjw^Ss^sM?BVU%av-ZuU>9-l? zCX=`Sdpz^?3AGVsY1+nO zVkR>1?9*qc;h|jl#uJlo&dSydk zk^LzQ7h({QJ<+Zk>|@Nmsr!ql=yzWE-!!rNI;b@Hp&?BuDCvU30PJk4|8zrDt$T2= zgbyVI7Dw_Yt(I3^E|?6@-;Y^)7F{GZ)=cUf%lhtG9_P*#g!197?`~)Tdoh+IifmIR zc^#7r8|z70PTcfdo?L12`X6v@YH*v$-@ra9>2;}Py_%f-TceCq78aHJOH!EH6X;}E z@EAp?gMu4x~BZ`7xtZU%3zL3SVM#f z^}Vl(ud18}H<0+Ip2T`JFUJg)Y#sAy1S(kn*5d_IF+g&Zv6MhLcd>>x_@{Qhc1bph zJi*%x1mmRvOeQM80&3%||A*N??U`$d8ya?mNS{|2C6Lu+dEC}tOMca*@o!ckXo}vN z^(BW@A#eQbJna+;P-N5jyq7PP7;~SB)ut$qMD9ZHBf=K^f2P96zMXl-`qgW8 zqN+CM-beP4#?--K82Lf(<)yG{&fcWg(VT8~G!@Ft88)EGYTI!DKX0jpeojp;LP@JfaJFcCY5np(cvDNp@Z%m9Io z+<>wAS&Jyk6lz~cIoK>(0WakM;Bqar!Z81|ZcuPFm?4Ij0f59r8ENFS|HSK?kHQ+~ z)EZW(!^UFLd^e4t1+AkgkABt`_x6ES<=v-RH6jxeubuSozAU2D%Znz9IB%~?2E{&7 zFDGn|Oo`D#_l-=OVZf8eoY>l@4-mipoE6>5a0tq1W2+7@H>S<67H9QN#|SEU22j}p z2b1dxofCuY9KZoe9$gEYi7&xY$GNrQmU=W?joUd0~O-V>jltUFM za$EP?RToko*|Zno)l#fxhc9|^6`&PP&)RV!i)@P!pk4(8E`fbU>Iy`ya`Gz6dxTQ^Dr-Q6hjbjt2@6?s_# z(kukDyg--kQpcrk>!jhFDQ z(tkg6&8pDIJ74voPAxdU0usnWqhnHv)$f#U&d$xJQYh8&E#QIyb!B+ohZueu{P^4) zMX_Wnd8G^NHi3FGRSK0Lnn=`SI0Ib4xVn~RIWY>X2J^fT_CG-IFgD}XWRPT9 z@xTfCq~G>83b`wqx^w%Ks^y5ZroE0{-DCIbK8D4&0&N|PAj#eeIzJXJ1uYF=2R!!o z+26tsF2po{*VXARv7MoA{G0x3{>~D4=ok>+W{g{ivZy&UH=jTe2ekel2PF-kdPH;qxm!{t0R1?=7e~MxbEEQ zBO50sQo_d@v}yB|`xpxq!<^sL6@T8I3GjBvB3M9SU}r-h!6FOYmTM-$Bznd5@!_k3 zl`RYv00)T9e8;tarwSI98JU$`PV`S&cdJ7c3n`oHy-g2!HKSW=WPu)gX&t{FBfIJ> zmL;?@(L$hB?&Fl%b5h)qm1L*0B@UuOnXR z79r!56hi;%b1v4WKFV1jZfFsZNlAzVbd#Ac3gSZRrgfwYdft=X-L3X9f`RgU?!{~v ze}Q3{l#~jkDO1yx2Oy{>+)@yIPU5fsJL$ptuZ5{o=I3nh&B4glsnLymGhNX)TrA7D z%e#za$07~24c^t2X?(I7+9UF=o zf3-!Gn+dTKa*Z4M0!dHr=aE4R?RyLj;fFSp9u3uZ)(dq&d?T+^E(@_Gyz*tS_S? zx79-iXnRsvrCWFBlnJb_)sjtU?$;4Yd($%U&_-|%+228;X->tc_ZBvW#z7vI!_fX1 zt7gf@Jgo-N0H(y*dl!$0M1o~|rVJDYI?KRzH@_V8j_#a8Bsg6G$m0~oeZ43{7uF17?@7Y#U&+QN(CD(c3ibpjhfvo&UcMSN49{% zFjCN4-toCYGYy>{8c&xV)0Hdi<{tM8X;-dR0&rNl?l;W{){}nRxvuD#KuI zr(S58dyz}%gWbpHFk6b#1(!%*DADPAL>FQP3HA>#ae;9_(qJYuAH-V~gHT#N7^$2W z(!wi!4rFMl(^jGx4>(Io%2IhOI*GqkKbRS;;z=?<>XI_opKYC_arrNl3CXgYQ==agBROuocytihd-s(M+tQ75!xpc9s)zD6T=t*Y7 z+nVqnN8I+}UX==fL;%WS{pJ}A6rW_E@?1p9J((EA$wtS6Vwyx5Kvf)&fQw60Dq0wL z2Mi#ZjgyAMhIoP4bNl{X_fF*(FTHvvTr&SKATO8tP|#}4N^QeEVu{a4u~A*amXrFZ zF^A`FvAAvEDRmi29&>HJ?8<8Elc(K9>}?{uJp6{C?uJxQaZVxZp_+R@pFF|B_OYBO z$n~f`uzgO6sPXhF8x9$FvPi8`sNt2<(5W*;ubF(HW!dmZu8#*~-}b30otd(K3qW+N zZ57WEZbg{$=Syo@+X%YXmaTZ)ZXwd^9>U3Vt=Dzy-snmefEg0xP+)@NA7&Um4VXbB z78FoJ@oJ!s4QK;N3TRayh>ip-#ZmzFFc>NPGioC63wyY{<@r3`U91{CC)Q<5*6*5| zL%FW`>Xd8-^wc8W#Qb%^5@iCc*BD6+`N*Uf8uSjU7)TKvFLvGwTgz}B>@05QL}2&# z55GZdM2357v?>N-#3xTV!kLxv=?!u}|*p*jsTs3by)x&gM^_4U1C8N{#s-pm=ePXDxw?jBJVv z>^Lu-%|2eC_WAVK)3#QOGPT&;`h}z z%<1t8s2wW*c_q9D_0Gc3ku_AP=!0T043#V9(uTwpE0S?p(rj+#x4S{DCJ)c%r}s|y zR;^)O!q#G_woVHOS0oWVmledRP9D{QZiFEw?K_>t`87l` z6^U0zIVd`A*=JZmE}jBq{3h^U^^*{7t8T_wBexT7o^}9v8FHd}rY6c7?BzNW>FETF8az`@*S%{i zw&}XgBG1i;2nO?xZbXQ7qw_D@($m?Z-Hq}Q;aHtlznNG=`GDw`oX9na9-6lY+2&LY z6P9al9J=RoJGQgV5TYg`M9P*EF1CNJ*{Ifx2Wkv2=^z!oiA34fWcXd4Ck30Vg|@Aj zi@(#t!;3GH3;2Ps7^y&ODYQjXK{3|ekguJRO8tK0oS>6+l#?ZIOLK@$%pV(YcpDF= z^MF$`YY7Pin-0&$0HEi|WV{^058QbCGseIVj}*n)mwMu|aTildhV8k0LPJ;WQx9%$ ztD9&uiriKbVAW0}FGEylz#JlXA z-UZw;m;U#~KKAA~Eu^($OjXHKvko4T8s+4))FiU7dys+}y@|4vwl6BeWU5MW0md3w zU;na4`(BH??zSZ}GBS=#)s0*yVzdGC&`HCF`rMkk&|RCnfYJ5NZcJ&@F(%8*Zz?gi zFaKx&nl2M?AakI!$6#xQYyjT;ki~jrS;LZ{pWr1-c z<+|e@p-2o{L-m_%+*^|=ou*ka>lRj>>M1$if`xkOiq^-k3sHi0aYVt6P9|l_w$Ymy zwZLeU;};#RKgHsSZ29(b!ta8jUr}J0LkrdhGz@g2?NuncyHE-I3Tv(E^Tycvue007 zG{jO+g}25N>v#a0ZqV72m_4Qg(5L-9ahD6Hx6ZsazW!h2Wnx!TSoqdooS(nHOURHl z`OlI9$<$>9Axb}~HC~Ur;dSIc_PVZnbAO$WIs-}d;qtsY&`F0Sfz1wUaJGg-9|MLR z(X-YSsW2`fX$zB441MU_<9jss>=AeZKrUB`x+%uR?Z_8uYC0+$UKZ}*ehdZD!bG|5 zM07fLmwG)e{1`s>K><1z6LZ{pY|ZOFn|aN_Q^ONT-A}7~w4A3@HT7-1FjrTiF>t)ZYj49GnM);!>DP0i~&>m zb7RBKHb*-;u-icqxtuy#2pihDq@693EK*XG^PWgcMnXU8-A8w}cE3dQkHJ1LLcnb@nNk1X=lK`Y|0gjs zl;eV=_=AEq{(x@hNKOqHopxrB`2&i>fOR!qTIX#TE{{f5G&2tFU2wcy@;XG6WdJQ6v~^R z3bWc5Mz$j!c>Xazne`?5zXXV^cnE3X{chEo5hu6U&g%5 ztPSxZ^>tQ9U-4Xs%3pG=iQ2eg6Y7{4P;qr+Dd}@KS!frD=r3rDK&z?7GARg>6JC9$h z)Had_5Afp&spL}EluSe%Xe>4Ph?wJPbB_KK+Yv;bSUOMN{Hirowe_Rd>+$eJPW+hA ztP|^nsmGUMNUD^YKNlJP-mG(Eg>$NZPNGDT%Lfs648z;%7)c}|K>|h+zyP-(9mP>T zyeb@v!SKS#CV4*9Pcaz-z5dL!n{o2eK&AviM8x=Rd47ej&%2=M2zcA=;=5K-P+t_l z{_6wbRdHG0CkVIaNth{?;v8_o=B5dQ$*IHj7&{NSEf?&)m-{XaAH|(L zRnZ%JRqIjK`4*Zpd@Y_h_qD%k`e`>=dj#0vdP+$@D)}0gT&tNRlK_*!77ogJ!ky~p zsWZO_sOr(^@V$Sc>30J41;5xyD~ix^Iv-#2@Bx2W_rxSwtQ!cSz3IQtPTlFHg)2 z`M!uyt7vH^jF4bs(|$*~hYw!+zrSZo(>Z*AEe0U`nFzG){Uc9H9w$6#RkH>_n}JA` zG9(#m2qdE9y@gN`+>oD9Devv#yrtlpfCx${IN#=!Y7VyX{gha5GI_R-u4!jm*pnKw zT4w9@8sl`H)gE%z<x9n0I_$r&4#SX3e~Y`0pMgQe9rXhR?Aser&kbBMRpd^~lE)ECYqJ)YvgT*fW zyLO)3;B65M(d5;(4fnCYutKfrTDXWS56+Sv->Q&ScJR~zLAity74 zq@0U&jR1wh@cebU)~s9@S(jL2U7h$Mh@lc42!Oaw2OU#k(#5(?zvxKL2I~jIM^1Wb z?AzB~udDYjWplc=voVEcq_;0@7t_yXBaT}_*6yF zF<~YvbhALPK-&I95KzJiA?tG2J;X1=GvPR1WQECdfS?vDu^w?zf&0;U3LGa8$A=-I z+1b^YtVsK^d-Fvt)vBQa_kVt?yG%WDdTd5bSf){2@;?N9Cfxn&>kv)MCoF{O)oFG_ z(~Y8!-%-gt70_xJ!ta|39)V6{8|Ma3wVcX|T)eDgo}O!CNf2zHX);0%z_VAp^=QJa zLSMhfbL7h?3w$3OiEAAfdx||GR2B8;O!>T0koOgg*02A#-_sj4b96HMHYwRBilDUG zUhP;YOXVe)O!{RxB z8Gw2ij6f!0Es&Ph3KN)q#<>q=k&h_BV(Rv|cxW*t5HlkxI0unY7~yDXReu6oY8E!f zq@>c->Z3y#O$FC(IRw&ziGTfGiSk{za{7Km$TOwgnO}OuJ@ZbpePuf~4`GPWqwY+} zv#0*L`LefMN@aL%>mG5vZ~{`sPe-dxNohGi7*yAO1s`!6 zq^zj-<6~ROj4CnK=Z~edFv}-5rBBD2PpZVOxfB;?0GRdKNLFdo9Cn3v$!Od55fu$4dGHzE!FBq45=Dfm^?Ab zE^sKpa8aiQey@agO~-j!8==Uh3N8V72)vqVFD-Yi2tAt@XlnPGFDz znKGLX$kNvNOXZS7{)WNTtCDm;+r`mvsiyLSfo2v&)gb^Pao^zN*{f&h-=nq!w0m!y zF9AY$yJ`!9_qVbdi9NcCNf4WdBBsfTCVl06eBdMlZefX%Ls{ue3iWl~NIoRiLhCCO z%TrfGHyiy+Jt60XvMrs`9Us}{#4`gE5`H1;Y`igM}qsNf~d4vxR0?er^Y3fYovx$@J8Q^HC8NXtl*1 z_gV&dFTb{qA8vK|Ui}4ueVZ)eOM7X}L|&*xNw|i)(Yyxh)po?^S!R7jc^-0K|9^ne z^1lzRI;iO1#uT+~zbh-F9xpK1ye+co-s8o=vCZb@8vP9YI_zBi9{!Wgjeztr=oC&;acTu+z zum}Wm-2$>?(y&s{N+*UlDciZ@^9t=qr9ytFzca$Y(dyITf3bW18 zM@_rwA$Tv?KH(+rX&Pu<}s)Eh-{-X?q|*eeve ztzW;@*l&uf(NKUTB_>+<#v{k@pKQ|u>b({S5phu5&ck6gYyZ`8R`l=O;?{^L!Yr+m zydp+}@n%1V$lDOllH=E-%hsNUYe%`>z2nWBe)P+Ku9`sT(fJby3u+Gj--SFpY2zW90fQBuWvJH3MPUA_QGU$x1PFmDdCxcgk z<#+Yjn>C*5w@lpg8~0wDb=C)}$DjUEM7b9h>z^_;z4PP2GwwfUST|}oE~8JFcU=W! zJslLxa{nSXl@94Uu|mc^Nw9AXG~de63}9K|h0g~oK6cz*-{!ba>PpdhtxZg3aQl@F zfL%5WNJM6*`dZXJnUo=PD|E{ykQ+YcyY|?PL0zdcMp>S%7N=Z(VoMp zZKAtmiGf#ccp7U*B^ zS;uXID+OB{?=IBRKhHHIH1)Wc+sEOHLuZe9sHq1?4&clGo>0mUoG zZWfgvENvNox44^N83*eiQ98>t`2Au2p`Y8-K)qJjk(qwrgbXtpDSQ*o+&c zAAhY7qoNL$PI>|r@TVco60;D3y-2?OR6m1kFIXbaM&ab#^-MwLL#beKNV6W%s4;!< ztw!mcW%}fK>4kFMLXsLXG3k+_sP(8}!x`P6oRzKGsL<~+*&-W6{nr|6&q{~KKS%EF z_;t5#q>aKFNh!uW?piUiFDwgfkVC8~ebo}drmu}BOZQ(yq#YTAXIzQ4E&l$46$gk= z>2*}N;}|*b25q zIa^mzy(H8xi)rlcQ8`ddS{yuX?Hl7_vfkNrQhR8N6Z^P$6O^afrZ;vMcPa-*SF(bk z-|+)jqrCl3Pe`S_%WxcW7yM?>38-!Ci>~biW624kZ>OY`;)5%F)c2d7AQKZ4WewGY zdChL)Dr5)D8wj5~c6aFgavEuC$Il!;7kO4Dbi3m{4H^dsiN3*z^C>JWZ6lo(0EV%k zy@t|W0!9Cl{=Dz^sNPVm7wXIz4gzvsf_@Xj1=}4^gUwAA8neup_;tH0iZ|Q0j`zxj7Wggl6&0IMtCy(j8!XJzb#QOZvJQi8J0$@pzTUd6)UkxmZ5 z-q^Z0-qd4TM`$jHjJ1E+<+t1WdF}GN#=kw@EmGAjjiq=Om9txuw4(>AH%CR|RI3#f zZeMv(zBr-`Wcs=*#__G-4AT!0U~69KoY=X-Spbu$1B1pAq@L+ zL~xX zT0sY*OZ2`pTVjds!E(G%Bxr0K5FRajLUbw?`u?1CK(&GLp3MEB`QfmUa(9#HL~F{% z5Aq2_p-p?sVLRHLs$2)Uv?9UZ3h zYW+ZuFWcNTdX;?7H}87cHTfd#n$P{^LXWJu`yeTgIKT7;Y&sBcPc>DKV=-^2wUV)C zE>-E5u2MdJjB(!&|9<4GeX$$A=n#Nc6@m>F36PQTW_}NHB!4V)UA7^g{Ce%2pN$%Q zFdK_I9$_;Y07Ek~6)~1*dI7R#cjw;JUSLEKw~Ps^>Lb_E5lOHP;qX~fWwnm=>FDN;iHxshO) zEa!IHq%XU}q>C2=hkj`Igxh-`sR;u77xB;2o}qVUB?%9LMnE zMS)MXi(le=C&Pc-lo&8zw&xqRZZn0tEEw4>N5z4ZnHP9 zSXs2WZfaNhA0B5Q_TtA~&G<$36FjVjuc>tQvUOoT@u6Hfj9&<%Kmv1Oj6yqhS@f7w zj>$bl%^4!cN!!Z6Ekge5@C19OtIwH+9P7sOU{+2MJ+SZh9MW~)&({hH%vMX23W`FD zuVF?&oj@R z>5taXp zj$JQ_onsTb2ZcrwzFgiPhZn3S&10SDz~R9xVp@>YpgLi8o$<`vv|0S`C(+_IZ;u^Q zlhe3eW9jJn*7U?>((Y`Bsi25AU|ER+tmUkTQU>=|LOIWkBkBoq3r@C0eQWn?bHCjA z);n1GkfNf%V*lBl)L@)*u#*cs;ac_N@uSuMoG_PZLpw;C=HDDOvR-6C3MM6FCLd|!O%LXEu%2xmHXud8}djf^r$^@(^wnH~wYS8tjX)iRWZ zLySn8iB_`3FW2a-D0h}=O(>hK)zrl9X^Q!BDGFP2_uCIn!@Z1ame%+|X^9A@i1r%W z;wGy(nJWGdywaIMU{L!(oj8UIl6up`+?i$oq7(X4M9zvv+A6m36|-0T1#tlhCR`I4 z`q%x6{(9nK>YQPEfA77g5g99}ulZsB_ra`B3|!Yc1&AD0t`2#9{6@v6wff~y`XVy3 zGU_%4_Q;V1hnoyGybAsDJRosEGhJ(qLxe~JP= z-uUEo!DMzuK|rf_WH1F;(7=|2vZft(c1;@DGcf#8TM(JO zMNMI!w37e!^~d+1sdd)Qv^+ly0P}yo&_{!ZlzjAV*@hP-77I!HqV>v!z)@bXk312* zyEG?22Q1I&9)*jV%CKvlCc~vMH5Ts;Z~MCFzni|8UT>8WW^+U{-8yhmOLov-1;H5+ zF6Bf2z~Ws8`?J_ng-dIj-yzc(kgI<4vF7tJU1C7P>$k5$$eW3vBf9`+1WCXwYFm)Vlz1*{UYV4KCZk{x ze6+Lz7UC8hg~qGf9m3$Jvga$E0!ABNQ8;_&uF$L|5@1{qswbNu&$?&Xb;7W2Sf|h! zlQ?XXUN8vSUL+9e=WJK*>jqcELC5;`|D547({`bLK{otDN=&Va9<`B|_q*+n9q+hr zn&TAPnZFrx4F@Sdqkre#tBx9{nNS}y5{RRI2&ThN?9(P=1poV>_7HBUe?UvI;2&2> z(kzFMMr{5|q@gw!80{>hkZv$720)y*>^!H<8BMsUFdF^x(+w-1r_bOWzx@YSgYo@j zfaeKaPP*1)l)#0r;X%Aff=Xj>LPi1A4d>ftr;}<#i)dr_1BrskO%rB0+!t#fK3!xF zj6ZX@^-c(MCpnSx`l$XVoY9cWgGLq>knVEDcmO1a-L!0ey2IM3qY5SgB|pzb5FE4J z45w#uvP zvmN2zzXufKc`V#~8Ns-mYV5@hLq1n?ZL`0xdZpDab%OqO#59j9&f4%UXIGd1uO>d5Y0h!Mb+omrGrJA!&InbFZWwNh~d@*4t z7Y!~L?*8VRx(89)Pa#xk?t7~$MKCHme+jdtN~*E34bFNvrC(rKM2GI&d(!oJr|gfV zBP?C#cZtgtk04ZlTL~5*!}T(JUgvMcq|=m$5%~!wEBZuKKnw(mwvR_SDqh z*!14~8aZjE6h8ozyKQ{rL`DV$#;aH9G*q3_`SHVl^Pl7Eu_}zpfO33%vIPRx?DLoW zBA1jsR$e^G37z0OVIOIN<t(`{~5Jj>yQOXLXM?u{$gKZlK%EQ^kZa9HbE zver2|p|#efBEmA)E+am$Yrr;j@R9C)G)z^rVE=1$OVbOT>G%F{Xy`WnbXk7PVeeJ? z5!@pr&H|}b61rHa*kGv`nk*zj*8lS$R>l2Ci1?4ybQ~W9w2duxeVuCheYm@eN7m|$ zrwLxYT2=d)%k$FL*CO5p1p>*?M>+FmR>4M?{uW^InERMgFh-squ2_WSm8UeP@8MdS z($;5vaoelJn$P<#uZ_6@OWoT$Ix{bS#z-ZRL@galwcYLPRs>RSDxhwrc7Zff`V5M{ z0?E&<7RPjm@nlk3(ttRnoGsMs+j+nA?g+?vrFVaQyl#qn)jU&M&}u31ys62Q7&u-3 zdAqoJC|>37tLaBA=JH3ri88Y0_X|xM40`u(lnm?;KJ0PxL+#!VxgOAkOILV=zEq@1 zKT6x$itdWd>CMet1GFG$HyA(6Cx*_xo{=+apPQ>`*&wY@zc+)RewY5g%FP8WJEn~ZGP9M z9euVJAt#D5BO>{4Gf}B`+e+V->AWith=U@Ey)8h#Nw9)_(+bU=237-T+rPiNS#GnW z)fHW7WP#JEr>yBXVek8AT58jVbmmPc`v^l9E zd%phL-zV<&!C2y=)~sz@h=l_l#A|VRJ8Sldrk)xw#&5%6+3d{?J%i9!FY06OD|9b7 zbXM_GDV0Pi!J1%-191p zZx#o&;@}hoh%>@f_z#bFTz7lb_F^J7s=8g3FPOV|!ju0dSGy{Jmr-kmsDhIkD0jgd zOHuKzt>OckfEu%jj}qe%&Sq*vm_ppm9zG?A_P-<|?*6!~CHX6KgP&57)|x9%`3(A6 zuLwQI1JaOAX=zY6v1Bt&So8N??1M>TqIh4YA^lJ3V$N8ck$$~gK+;)!3yE zY{R!tLz;}LPWNC?!+1;`REbLqWfv9<=a+eFT+ljvF~t#;=c4xU-z~b`5S(QP0I+yt zM0LnRAw`%x#M&;dFg@Y){rghyJD83uZtZKH6K>Yw7<=v`RfMV&*)6EPBVCVU6j)Cf z(jk|QkkeXjHB!cu<>LZ!{cKuV60#C7mnER97wX2?MB@O!Na*C&t1yQ=MrRoqQ0A&^ zu9Kl4srZWFAe*b$KBai}?Oc;A$%|IFO6$#1kj!~}LC`LRSGZuuueC1YK5bimBThG1 zC=-ZJleIBdD8DH!gR&9~eXzRn2h@as*vBOdIBkN}DDS6!9Z)7ajO|}4-EjmiL>BQ4 z>nL4t1S27Z0QpDCWcA}V*LDWo#)Ac2x+p9?{F$RCs6E#y`{U<3BXOXKM zBk^@|F(L+Wpz{OZX5vwh6fW)*&0E#|-8dOO8N@fA7|$bJACT^291Jc)z*0j*V=BoZ z@79OI&WT9HJRbB*2~mI4vbSb1E^+7$20W+v-`X;j%^b?iu{7XwP&|P!G$gatzy$bAtA89sZ( z?#nTPW8d$a@WASjP%rbsG9pcd@VKe7>fXgl+nCchQe2A37%mA#WQBjS)jjq0`?s@= zN0Ua1)2P-$83lRK!Mh)%yy_`r z01!-C1PdyF1jhh(KL}MRUqv7GcGw##&n2|_$(^Q)(o?w6aojv56QMK6Q}SH!fTBn^ zSu8Lin$28dMGV<^bTey>l9;Gu1Xhc@qrMGNP@m4KD^!-E-$XYx)~N~Vk_;5ObN zsSaWc>$&ySQV;gdve44WoX7mFb|b*)((8xC_i4)f95QgsfmaA@V?%80G#8x;Zq$z6sEqubhuh`?>7AOijuuLFf^D6k~0v}WNRM-T{X-b z4-~%~rA1iX9*xHTSeQG|zRv0J>j|m?gVtdTX(^}6n)Ub<`Ta%-+yxiM_%0OnIi=Rv zhFl~*R>W5*pU7*|_3o5OC62T|>X2+8C`t2LGdY5(DT2pqu6G~zzWP(ct89pvPKj$8 zJjrz>Be-~LE(p3Ui|WU5+x1+{c*fl3O{h@V{H8h{Tv&a=riyF&N8&LwAj5?5fFv=r z1tmV&I@>PZ+InMZf*rX6?hm5iPYX&(L@8Z|L2bmNs<1mhyOzDDqBb` zE)JEJ3_#-gQ$)FhAUtq*!TAiq{{cqD0H6?32YOY7068`FN}ZN>g}Y_s>6%(`n)m&Haxb zH?}hKcr@RS-7udi$Me8ZR5TB0f8d7W5CBw;7ovXY>Pd52GXO0X-`6onj{{%;v@o^* z?#(9-hgYW}Oh2^AdrBWH29TdI4108EtsM@ArhZbMQ!1r^7FepA?3FEr*z*DyAf>yZgoh|y5bhe{4 zW`@VlD?PpUMccp;sm&V(JTIy0``6$-dh+{L6HWP5^B0DEp1u8K+qh_gcfOM_z+2yR ze}>rEn|60+oxRuVRbSYma!w-seX^J?!6a;#AkYlU9AbtfBcLGG1bjdOCER}Caa0us zIEIE~oC(eA6XL>HZ)nu`Zhhj7HUAK%g`OQHGO;jz6jWF}(}CA1WDFW-Ins3Rw)6TH zf9Pk-n&s9f-|HD|^?rPr!>3Ni~%jX>$xsxG)-cSKkSvI z%oG%@%!C&dLsDc$NvCWrgUnR9H3itJ>0bADr~k?IY)Oyt%D9xHXzd;QIO?X3X$pNy0UK|7isWzWL_gV_l*V%ajUuuM#Xj>vP#UJCUo0QREB6JCZUC z+3ZjIWf|jtGOpF>Y z4|h#qxdmTcoGyXQ5aNgWJSzosE$4lGx1=syu|$%DxI?m{@Be+_NSphaB@3Bt5e!qP z*S~aW>?r299~Il^=;e&nw6q{6v3pge>?o6{O6os{q=sX zj7x7P^$xzRO!+sizx`!!7Y(u;m?6#o|BVsSAgIgao&S?%&U8G;>s8k*#|#3nL8MQf z&eW&avtRLpRkn|XYm8DV`$XZ7Fn*)l30MlZ=-f=5)U`8btfGt}y!HNA>-QS{iaEi{ z&MUy{vDyz-C#!d)Fvo1`u%@mB43Gkk9<9ZwJwN*+VD|lR3_pV0lMQ1FrE#WzMKJuxxGvh?B$7xedbEQWHVx~J)$DX0Zu1Jp5 zw->tBzEnS6GM^~=VB-SA-TLh%x#Z?)|}@74bRJ;wLjW?-=h z1=-)=g8;Q+FbHzOny-Jyn2ZCJ$8i84hb^2uulzqi?BA#hngwi030IcR#rYTDL!neeL()cb69RSLB5=)&;mQTBkcm@u}`Qclrn(qK8} zwfWe!)h;6oJiH;LXJD(U_R86^vIj&1mDCF!bGA`dV>)+BmW|~!tOw&kkN>jDpOZHx zzP7TrSUsN?ma8e*wNoF@zCLsOvx8BlWkREB$ORJSm1DBI+wR@3#&rrA}B%j`dBN#xU=K z;nL-h8sf^`j;;M`Ru#N@6yriq@fC57@BOVi7#Vg*!_8eBKdRGlx0}ogsh1WGNfnYw zOJhXXCdG5RZMKffdMMJD2DbJXc_`~TQg*z(0qtD)z6bIB*|pnnzzA7!A^P_Z8G7~o z&e^=~FEyYsb?PJxY0M4NyY|d@L!^L4&W3cuhw|0MjQ~< zc^J%BK<2W*O7+nADOFm|*fss|G*8$>);2LBd;T2-alsL&hzP6dqP1O25R0-6e~87a z5>}j?90=MNT%A#*DufFG<~}<2@lMGl`HCb->HZb65IwPa)~xjRy(c%VtE*+ISkeCl zZTB+v*KT}C%!J~K9A|rCPZn^du9PDFK<}fdBd!}~{WX)}0eN63986K9G3LLF3&R79 z*BU3yy;h&^uo_L?kCsNqhF|G9_v@>rRdlR3C#g5K{Lz>2@M2I z2~9LTrVP%eXr>JZ%{q>ys3?kNrskZpso7|bi00Jb&?!?KDo?5P%TDM0p7Va!_t&?t z%YV4MHqT=3y`H_+y4QW%obPDWeB=vEg#X~N4MyxlK(1IA|#eUKgVe>!aowOXDS z-Q^s8vFP}bGuVV3Xc~s(x7GWy;0s~gXU0ARD&<7oyDWJ9xAo@5dtJMD zAgO@*E|)A{js2hy4xj{3NvaNOX^Oa*|1>SYr3D~_?7rQJ|E!+lgouo~);%60TuJC8 zBbIsqn3>y)oqZx9DN#>qal6Dmf0itNFVEpaHwam+zmBKfih4XI|jcgJ&+Lv9Yr$U+(!K^o7clQY@at?7ADa zvG&0Krn|T4@}=3=6KL~0!{0Amc+)v_n9KlqGEIcO8n@E^JGG!=CX=+#LCZb+0T_5( z0i$Hve|B=TD))ptMd62uTRdP{8pZy;AfIS=f@&KctD3RRSmnT-7jJ4ktUUrl-NWhz z5RG}uMY*w!i_jWJx0BG3-yA=|qJ(fi!HaKU#|r`J8Qo$LS4M zwmbs<@6Z%dcM7r#yj^QR{nWNmyQwP5GyJ_w-w>k2Nf^e_0PJ1gq0MOSpv^ zN-L1}GOuSU>KSX*woXvA?a*T6_kVAk%#aM7JLjLv`o6Vtc>YPA0Xov2OMm+9DD%6< zgX%GW<_J(V5B;%Qv2kvV_+hqrX|b`wRQ#FE9lYjJstKj&t1=PHqS@T82S==L7CEGK z?Q@%XGuCc!sOIxj&MDo{3Q(G0zu6U#-5DI`lS(wqxf)meNx#(4l##@BZ=xeBr9y(wuMOMmJXd>q(B5Ozc*5;KX4I2f z8~>^^fywH>ZuQi4UY>DlJ*mE6o`IdpUKVb76iwy2-aPENeOuOt=*wwn-LPr}&(BRe*qHI~g9 zj1r*=o_8JUGU|dL?vkJd9mU6t3PUXOJ*$tMqXHJ4W)p6mVIR{QoX>7lW)}{a$6wjG z6@)kpT4iszaKW_%*`8j&dvFPh9VeuA0N5Uq_@i0=w34N zw;bR(j3kMg@4xp|GFa%a*_%rbBd`)NC<=aH_WYMcL{-_{%GUhx%3awA=QjJ1FP74M zw<*E?88J>RXp1Y=t%u4#HHS{9Wa`cA(sUNE@bL|4$(AF&2cNG+6s+6YDrRoL7r7RP z;&kK7FXkUTiW|*As~L$7UCs^ne-Fl*%Ue_^#Q;pH?nKVVcVA=Hh(9__I;}!NRFZoC zw3T1%V~&^j=~I<~-%nVLJ$-9$wl(^$=Oxd$UFnCYxZ#6}!BEd%N&9_~1E6A;Z(bgF zI3Y;@pb7wgQr05Q)gJiIAFDVXg?yiteSY0IrCn~#*hP`0!AKfOJFrZ{uS4`O5f!59 zH|^$Cg&%kq(4lcDv?v$-^0nktlSxi{&c2dA-CyrIuyjj9XDrTR$SCemtDB{SxE2*; zJ8GB}eazqRc+~#75IxhnboKMG7pmg}UDFD_2BSuw?8!3DV`e$}Rvvz+z4&kUT^C=5 zOb9@?%)M_|e~|Lvf^)@KbubrD-D}R4wl^k`bF{S))N9vnzW(3E|M|TBX+7|L!Y$^m zGuY_|)XVFCb{RR3gEM|wjR>W)AC?&M^xxilmK7XMv zCk$O@FEA>djww~o|KaoP$RCT%OFIly(2!DK`r?Z#xr>LsOQHiu2Ri&9j=k{fw*SOH z^YZd?uu2TSgqAnYzdrC1&n&quMk@;T-F;XJK=(fy+0qU4^pbi&unqVo1*JX#kYpOP z5p=uYz=BJ8^f;<(|Kftp5D8WWbVH1<_ysCer58D5T3A{>hKjtcxjlE`h`O>skGRWE zS(XPL-(MSDei}1$pl)fbq#(47gf2E-@;9&O=;YQLXw>m<2T--kE$V6B>c7s3O9IzJ zj>k{TEKFvK{k;nt^snzwTw|8|Y9?Qj{t+|t{pQ4_?IYz+nAz9RFqO8o-G?^Z#$H`J zoEx^(3^+%ij_*#NG8AZ|jB|{D9Vc@<6_(4Ns;loFG~amf{DUvRn9o!91+QZ}UhW6; zE<*4Rl(K+&frkBeO8|iQ%aAXH&$ltYJ?WU(uY-65Kq&)|oIOo8k=?g6ZWS9b54arO zr<}0&w$b7XrI)L2B+0SpgEMV{@)QHp&d`qXmmhXONT62Ir<|FW%lS0SmAvX5@nEFh zqE%gL`*(h+cK+hbi}>G$^IJSP^D!F(g6l;8>y++CAV*i`vlkmhZ?eAi71J2SpsPjo z4!M30a&w<9759vWxRaVcx zZ59L0sC1=rK%?Qxjz|C5^Pigmwj`eXZ{~p<{D0%WfBC-y0#$--fp7gk zuK{HU6f_f9??!Js(e}`rko^6@&t+}hsmigVx2p%W^}aYn3=b(5WC^;kf#sERufuo@ zdNf|Eh{Jf#h3ixSs<&+xt9`9f5#pI}Yqp9u0VUh#6g0}!hh0Tivh(_s#;_!E+~L<7 z%haJZBYC0C;EUb2y9{|ufnqqfU}zA}w;+`}&df|$p(OV0DYQX+7BLf3b1MKaNn9!P ztT&87>W0pi@-hv15!*dON|P}Vlg9#-M7VY3f1l9^cH9p|I|VJ9yzntju^xSr=%1|^ zh>eX<>>hrVn z6?Th89ByfB;^jXN{(a}a&(QWkVDG^KkyGPDeg;gyXzOK|c{s~ac6HqGpM zcg)Yd8#X_AYDcSXh&g69(`^i-b7+A{xEU-Gu!fBU!YXG_g=xJB&bPn+SUy5;y`>pyP{G~GOM$?$AO z>nffiud9{U&hE)RsV`laL(p`fF3=Vr{BVdo)2u?C>)H66lWT-eqRL#!c79lrrts+T zhi&YogO`8Lk2fg#bYXq7W6FS&=TlTL_TXEU0iTe2<4N;;svgH|v`4vh#rVQ0TW(Fc z8#W8YqXMGWLi6HZ+B@jbaVPWIVtOWmDxxL`hj4ZfO{~(J2eWl!<^0qyiS^<*@1Ndr z%XD6tN5{(Y^!kdYrlNW6U;fSVj;{|3o=o!`0~%=|!LiSRy$$h_qy#@&wuq!&TMr%i zrFPB5OHE_ONE1tw82SRxVl7>a3S={HY4Od84gRJiZYW4!8_RlCWD>6gI059{ln=a1vgK9h+j zez|nfYW{8SL+7@^cV{H9e6IinufuQQ8~-4mSYb%eO*RBCmhfVmhI+AE7`@gDNWiAa zx|0AGU0!s!Z81t|@$Qi@d0~fl#GAK&zf%kAjJsqrI}|M5F?i>M)5>A@w3pB3dvE^Y zliq%I?JfAc9UX>EsWz+mR)->@<_5fZhLKnEB$~Q_63P5A*Rf+MXL1e$#fm_R6`e+t zn%mB7J3rF4DoKyu2B>AP-T&7YX#R`E&HRbBi?P$R2VJY|#adaLo?!UA;`*=8=8F&n z!;_~@MLyMMU-J8#kIORZhh=eXI-hs^&`&2Yn<9(&x&zAF;h@iaBuh^Kgn%^ zA;6|DGJ~?em zUD_$V@r3?T6T9G(k>fkt3vCv~bX=E0?52u+tGgie-wfD*JbJFqVpne z&t}1-h2~W)nub%=)vAffNd%@pJAnLA7e2NE{5&X%RZ4%upZL6^degqdSP>8eIwPXS}MP| zs<--TD)+ah-O2gmUn9Pq-PqiF+<4C^an$+qU9a1`CR-TM3c_IL>3=R?v~amT6KF9^ z%oDF%%JS&N@lDzsO(I{|ezed*jfib@%uJR#C}dPTsxnzq1prz`!#!mUz)|vQ+bJ*e zx+aS>=h!zVPM=kb^}d}njoVN>teTR_w+RN=jDI@)w1dj89?LCZtqMes7+{)BS#lKm#hg&vzJg zO+i(!l!fc(mg0Uteu=>r+?NIKP^8Bl)?2$S*uEx->pF7y-?mV{rkb_(q4BqWt-fsY z?3ir3?gJK*(|vq=Z1Xdvb!{Nm3xYD+HZ`2sK#;{?6in$5ClK` zCF#*PUAm&2@Lt!iGoq}ZCp#y!$p~T-^>MMy=O#_s*C@z6*t1$PuPFNCP*IFc%-60d zk&|wPxs3Z0DQ^<(8c&suh9g^2H3 z6xXuX%Em8fM0AHv2&^e>oaRB8a5Vw1CP>9?yCVF$y9AR*WITJLa=ozS z`mE_)WYdEG-QQ2$o@u1Y__6Y%N4sRXcbuXo+Sg*cF3rn^ZND2fyxW9R(9+moow@^pn`5+`x1?c#Vd4L)mi-)Uiu)GDSUR@jrlCQuLZ*jctd)%Iif z#B%SY)wauxk=;F#f~C6C_iQ$a@{{GZKR&Nz{eElr-RZO}V`-$~M*rMqQC&gj1YNrJ zk;B((Ka<@P(mFjjs&$Q^CNbpZTLp3&^p!n&LfNixy6H)e0o_`|TNQLlysEwEY5@FWNG`F;=;=O+eUvqBIDcF!?W+)!y?ZPZ`*Zlwrz5i7J;3p z*)y~-YdGCLlj}HXA?HocvGw!Zyb+~Iq{Ms1%0`*A*7u{eVz-(aS%OFXY$URUYcB(c zeyMdcV1hLK1X!av!xKl&^8WXCR-Ink`+2L)pTBM9payLT@4w8wsr5b=9!VIwRqA~C zvh_i}&6HPrZc!||roo_rpyXbWm=O=lbcN6i)5A?0#Y~|*k`A#(jpI76I*_*V^Zjz$ z!cPS+t-ogYA1EC@mp5+_tGHt;m`nb%bLQ}++YDLnZ>QUvTW32a)40;9&XD0Fw)G0+ zcn4p5ONgjD10PtWfe@4%=k{#EEiSAJ4Ao5P5U81&zBDIbSVzj+ zm=~Q7tIKEv{jmNvH+}l2vy77!-Kn}S;$C6r=ih!>ALMk$eqSjH`%Vj$ zgR%yD&=u)Mnc12!eThr!YnD}L6T3OPaqggs{~ast^Hhz&D!Fg{)=yvF+>GP&MAMfx z%qsC-5!JO05!bcZy=H4Kw()n5L@#l&2zsBdg?L53I2FmyHMd#qTDo~;zSmYZcX6aW zkD5ixNm0K-$%H{*i6&L?p%c(DV<}HLpV#sy4clQhbx;WTG1DGCxcFtGi}?3YXXkqK zgh5`bH!pgWq0oz+mEQj$|F-xdEbcWIJfl5`lU_@mRnqUg&ksJxBA134bK)l1e3gu= znY71|l2VD$ggTPo#b%=;#U=uo`V6n1*AidLn<^&&N{d!af3k-ef@d8syq7uyb-a^_ zO}76u5jPLpej9vvkxA@NE;`Sg>RMjC_*s7X%pxK6PsW$-``=egW1D<=276e!2(QQn z7!;>$q_dsHcB8Zs(vnRUN>&WYI%;^p)(>%;^J$9m=%Vvp7rebgj9TLlP8FRdo?Tj= zSsLuL$uj5hEV6@UyacbC_`lvbdihgayFBdTEBq{;Tq?_P_f#i)K%ij$Uo9xd-XN9u zo?F7+g|A8vk#m4;uOHm_-PEE;%3C!Le&~GF%ngWapA1*DUkJaA=))^8{DYFp}bu@;8r&W3pa5R!TJh?){A*}SQ;W*;NlT=tFx z{QMcQ@@auKhKN=y$UCA6gGMXN5_1nu&r3Hd1^Uu@hT`DBSYY&nf;QvflUbp(p|sCy zK51{aQ)Oag4hTJ?G{SJ`isIsG)<`|u+#})D{e`G{v;0whKCpF+f4AsI_%HW!%gq%x ziZ*RNG*>#ZjvahuVRgrL9xoZ7rTyhLy52ckMGzF^NV4?S>h$V9=MTKfc4>yG7u+iG9$LC~_ZimZn9*6#CgqvV7UP$21+vI@I+r#&RpiiFjLHxH%4P3925 z*7fkCiHh`f|GS5#c1+&?r)j3Dlrpi_`2n5mzw@d1e8~MT?Q(%+r~9|Asi@}!F<}S{ z?H3lVM=k?Kx`<3vc08JY+o*x1qdL(H%jA{UIpI9$s^x?{VE6Ntr@cl0`xO254Qie7 zR{D8zy)>`ae42m4TUj|r%Gaw`ci_k)z3FjbD^B^0{$xF5ztr!A9&g+*7ympE%hJzD zg6?7BOj4jjlO@l1fQBa%GccZoAVGd=-_3pan;t4!duW+5c-=axU+TZ}jZc2PFv*Y@ z+0Bs*P%C%;9ajT%UMtG!2M(adEf(4dT{ZqTmtSIJY|C`~WsTpUoA@;Q)zRk@Mjp7sZ z+WoL;&*G7*aTD$tA{8-5CXbYL_f5J~HOrdiVJzJoOe19+nnUtztg?3xbsQ&87%34& z|IOJzB+mM%^MAYEWtD4r#Twt2WlbKzbazXJ&Ch4yrsLrqFC41f^wG(Q5=9b&S6b@C zdEH-d##D1URbZ^mPOyTe6f;K*@^$3d zjg0g?5d)P2{pLY;*PU;h6SiyjKOK7lRyRwppY$9eh$>9jT3A^RAx)vJk2YzE^9qGz zZzmAMXP;?da1~0XHI2a*zh?7T?KQ=tE++BrtY$a3J-Rj7&X6lI`9FZeONm?{-@DEH zr_aTpmGf!*>=$m&5SjKOI#wc&NK;4$V5&iF9nB?JGnt%_EX_#P1gKtllhk%Et~@kt zDm%5*#SN}zl0%j>lWPG(KWx+Q&s!bNuMkjgyZm<&gPIUu6o(qckA_O9h8|hAYiWEV zv~F4FbaSy#B#>ieWPSAtEFC$|uB;iTe>TpodE`=NWQ44l7{VE$y=Zn4{ro?U&o&VX z|F$3o7t(OF!L_4GU;p5Je!DylgDy}hSp-6ng|rWiYonj5V$&hHNS*+T(X=}w4ti|D zs>mrkQ%cv;aVx$>7LT|9S3NxtjEq0*Kk(Li+TTjo8YRcBoxi;A!w-WjaSMe@kw_1j z5=9I_kD-gOENmi>ETr|&2-w6#P1ue2;~M05{9eJ?6O+z)Bl%c}Y}~Pzg?kH8!%X2uz?cr5R@u>Iip%sg;h)Z$;|= zR4N-Gp1n6fQ-Pu~^QvnQ4!$C6BBQD3yhNnhTGR3C&c30P&)4tlt zxGIPV^(S^Suvm;Pu*ElFJEpOwjslc1Uy;RET>^lioER0{sN;>UrCKL-=hL_G7*ZmG z8=4np$Bbk{@m5w|qS(`KS>A>7RjZs6&u zL_)JW3v$x!c3&Fjmk#ypHAYcML&;Y(0;LmYk~sYqH8t&Nkuq7rM6Rc}>g6~f=@DR` zXl2CfDko@SHIWXb6@AbgM`p%%ZipSgz~~l3C6;o}<3!XI zYor0qLheWQMtWDJ8keY9r15xEHdeFJgbYPf^pQdK$IuWrR#j$MN%l^Nf!pb1+VR=- zO7oM(L)n>V1Z93Z6^jGiuE7)Jg7d`%S7c7Dj!wW;Nw2NKLd_hk-?jHCqcalVuna(_ zg_T)dvj{gU);AN+`x@TpTGS_&hhdX4v@rhrTS*88^_Y>UO)6*0sBU0Wn_G1rC{QGV zlChOk2?T~glUR+)9sqO1X&Hp_IRPY(2A5N_(faBBxF&2;yb4N^sgv-On2E)lPWN+; zm0>N%JId^JT^NG-JXkVBXMluGpfmtMy#A1@B%_`9$y%3`GD~|zcbT&3r_B|ky!HVa zHbHsdbbp>cV%$L=pM=6mdJq_IFSBBuV#$0j)(cB@w5Oq!$rvO_EypntLL(2%G>*Hn zD*Z|JDX@JrQKK|eTB(SXK-0#P(ykH;83VEbCY2z?X9T4d>!@BATswnYz}Pn$=Lr*3 zG}!=7JkP0zmegKr5mb>YJw?}wA-=~xwN-t;SvqJWqT!LKBoS3q?rO&9WvsEW=E_+F z73GfXQK1ekZBEU&SR6Lt^7#9yLn^0KD4t6nk8US@kGT4UXPB6ZGPju>)KT z~GfWbH-D13vOsU$hR60WbAj2hrk zu}1eMQ;pc_e2csU4_t;w#MV;ACb?0Y&}E`{NMKp9kry36)7=8LwRwUSe=@-gdu*p9 zxl(s?!RI!z{S+|Wxdv`KM6GxLUaVUM5NYxeAqjz#GXgT?;L-!{Qh31mR4j5Z3`lh$Mh&kJBOkY$=rjr(*otcU_y8Y9}Ni$J;?&fa23!;YQz=V zSMN|h!9HV;Nw)rWKKHKzuh z0eIE)nE)f6&Crw*00&@?43}3QG*VGkCG!RiTDcOoZ2yFuCm=|)@ywAuDiRBbHT0FQ zyB)d>D^jK)?92wV0CE$UDFI(x zVUaAiMs`}aoN8}aNo8eY)$|eI2Bw(k8wfo-#W*Lxtr=imZ3F;9;nS72PFEc}Kh$%C zPC6Ug%D0GpOemCr4wTbKr>pTSR3rxRjyhLU5D-{eCIp3UP{9E^Rg_4`*8noU5`=PW zom`0_8vtZSzf+2T6PD>Ed^3iFz|^fbmzz$Nyv!su7|8`=Mfbkt92oRRq2w6Z0@**8V2wIi>Ocra zjb}7ys1*V@mM{s+%~#994+wYYs%b#!q@8ZSma85@0JC*s#j8LI2Ynp!^x5IsATF;C z*^lKPtW4HM`0tSA;xz)X5(L&t^%hCl1D4o`jX#6XOlrYz_wew<2-S*Rpd%&#khy)u zY~p1G6#1l)&aK=Nkv=V>;U#$zV(EOc*!OzAA5Gg8Wz6yd>;G!mktnhIg|?4dRt6!G{6<$g^)4A~P; zrxlcl+H6$S#P)EoJjuk^X(?ZI=O`x$H7M*#c(GckB~S%(0kD{#?gKOR5LGxi$u1ky zB<+_F=ZL1ZO$3Q9w;eS^b#vuqn}>+{>8{{5p_)kg5-EVy*`3s8cxpv6#9p~N$6lHI zd(~)NEr_p6DtXD}V5pg5fnh9NHK@&zt zsvUzS(B(nTQXnRDjxSC63ZDkX9yKyU0Stnt?i@ERu11OA?jPv+C{ZE1ANpd~4>Mg*LI>BC!`Y%{xs4lru6~a{{V(4t}+` zMlu%El8sDPaT zBB0vd)I#bwD)vas)rCGGftOOSzC4C0yXB(B6^jh|Rn+VQ-G4gd+N)}XnCJjlY_@FP zoXL=YwH5@SOgXoaW)acL<5+;Hd>%vSVW*>Q5ff19#|uUTmbPLrnn*hs8$$)4qoS8v5+Gb= z3B4dQM}o}tyfeP)Ska6`jJg_`5=+QD#=_^G_rF|h`|kpcgQyA#*tV!D>}T zPK4x;GS#PrO77jPAf%NEU=nX7e^1RYukjAp_;)qP4>pAt$+ZiVi(ZHEX9BBY*@Lp79cBTz;OZ%dwIWpfvl5RQI2WmT)@L z4B=(c%~r#bW1Aj?_FsH8U)05m0E0J6gA5&G?LrZ6Ry<|Ipj^wr7}>!Pj|{0vK(IS2 zY5ZCZI$g6l$8xAUB@;RWKk{T$IG)3C)3V#c#9(N1Poih}=CoL;Nv>#;J*YebZ1*hTG-y@zZD}+~tqCUfsi(S+9rzg^$g+2Yr)bd--45*e zr})*24ZTIWv!C0sDurYSwOx)Nw=}T^wV>{jaij-{rAzWB{~}nRMf1Bwfz3?Olm61@Mid>6gO6@ zD&4QIB8aP+j7{J!NWUnE?^IIWxCQR<7*D`!^0TtH+k5$8^-1;cAac@Gf`FsLEgSJ5 z(UMGr02Y9bY-_A^)P7J z5Wk=ddotRbGZREF(f8B)3n_$B#6mUFr5q!sv5`m0z$-2Ny@m~;_vEo_0{QuO4x%lc z=D9kI`D%%Qx&gi7iUg}a3ggY{OKkmsMH5Q|5Qv2ahUom#a935mf> z?Vs!xOm0Op1)LeuY&iOlh(7p2lMH*W(K_F42q|HiXP~g zm{CjV93#rLFBn03(EuzdrKC={n@@s1c~aVnPUO*s4|YcmeH`wz5Q8|Mq)wWW!OEy= zmW{oLk~XK3G}+>UX@m#e!uV}ztN9q>p=p*`T^J23;CboNw9pgAM>C zI=m7)L-hzj7O|(3_gwFvf0}Ye25syL&$TL}leMrtJhfVgCNO~$^~*s%q5Bi$4Cb%* z?#VwVzOmPFGC%k%BiJA*!7i|5GU;ZZ3l0g*q>!onB7*dt0`I$0HW|{Jn*~=EB}OeK zDm%E7&m^aW(zQ&0)=})e`Jj#PSN%h%$bmc=8UW5;@WMEw^T_G zY9e*Ve9^^sjDD4|wj*NxpaQR(ZEt#L5feyYXJ0#cu>IOQfubn33xhR zyz66H7&W5kGRv2KCqsXI46_S%G8wpZeWd1UiWsy$M?&ZoBTxelKjvSEFRI~F1pZ{8I}s;L06~UGLpyvp@?;u*$r@&SwU)leSQ0BKy`yP8_6rc3KHf zBRF>URxPW^I?@T@eELI0>vaE%>eJDk*NKREHrt<_VHFxsz1zRt7_M0XLr}44Ulh^> z%6$<2(iV0~FGBiA3-;?sDkTG>oX1lg?MCXPn^7qD--b>E%>=M;+1Cy_Ru;MqL@(d3 z8%tB~uGsSZaacBlZ|f-#_+tgmGlJ4e{jo=dQubJ}>3b=P(+8To{4-*(oBDk|P{ zkdhe(W5KVSK}-5ih1P92CNysS&7`u>)o`Dt=HPe@ESlaq2Ww$>GoK6diA{fTL z^EW1-6kD1eJn#~vVyi@Cqa~yz77tNhpy|g!nSi&Z9YHB{dBwiLZ{g8gx2Nd2!AfmJ zhrIm>nWSXk9qcK){UHinMl*IvL{O9W5a*?D1$jOA#$)V!IZhWr-{X4VHkl$s=ZUD^ zuc#H!34sJ6@Wlw%`0^ZI_X{z|5KPR;tfib{=_RwcH)rB<^0Oao9+57ScbSMT;0 z3qXKTk&DQ@eZ7Z-O~5s|XOl_FxkOopj}Q%aQ>OHpb+ld3p%ZfE<3wA?5L$@ecSL zm1+q|gw+YkK?8{v38Xh36k!#e0+YZymTCFMO8%Iek$e^izhof z*-oW9QO6V1!ZxISK_n#MK60u$n*Smy2R*6=)q>Gbv^@8iq8;55#r}+p#Kyk*cr8d2 z0ANo0@89l?+o4(oW9lO`yu&@4MT%=-E}{`!s=-Omns+1wP+c2Zefe&wrl*}zVk&}? z)?}b{-J?e!*O#1qq}ym{GIz zUfx=F4@O6yfEK+1M2>Xx zM@`$d zzYXw;eUv%s3-1VyS^1iSNl53pQ?VjbVisyeTd$!~ssOhn48c`Gvyz0~kZ9{bT$9b( z-$N#*7sT&8kc(P&h#Dm)=$%p|Z8AWHyp_oxLn!3kAA{C@fXQ@dDcrp&d=r>R$?J@FdU8^PreF|mWEBbXv$7-*4pF}jn zkAu0~F`nS$$r_e=4^#eoG_^{p5E6DXaKz9(GdiDw(BSJ!FnsY@DlLykp=u@*BwIuY znn~5qE9%^;TeEi;o=2wBi#7-Nc(aZP#6VS3`eX@1VHozQ9+Ckh1;o2tYXsVU5A2}O z?c14-GMywze}P5seo4)O?a% z5@4n_d}y3HOoT7?sesQ1CpF#117jb*BGhzAnfXdsnXJ;H*Fue8c&=MUQQ=5v0Xc?v;Q@y^kZ(8;94!TmZ~P&Qc8ChJ@U z>0I2PZeHcuf@pqzV@n(vCWgrntc-gI;0+taPJfZ+yB`+1Q>#L9bbUEDtcL z-8ojxaubpf>Ji-%9tZemuBBDnydxz=&3%g3W|NUD$@hX&MBODIEMzF54AY0nW)*9; z7RIDzg3Zlv;Pa!uZW2RX$_VpENk_tXExa8&N6+4(D z%eK8=bPTPucK+2R?=mkpUV}i#iCjDW`dk2vm1kJ9;~5--EB0V>bJ>aY8RC&LEqJM? zxTd44E_xQ0%0Dtj^>9qaIIXxC2ePj6{E1S-?-XGMed)p;XgSk@3MGTrc4%tBL`uCy7aPh~!^y>NJ7pAy)^VSf+DEztMP8@7F#{=? zIw?*A&_T@fX#??+Z#@gba`9T68Jcj9u3(=*da&)>^#k2uTI16{`_K73uqD1%4U0#1z1O-IXB#S#@bOu%92@6ep)&=7KJ1j$dc_j zLNyaJ1GQg0o75NFs`Y8elP=9H)Y+8 zVkfayanTpueZ0MMpwfM&zv!g4aCf>&$NCF@(cG` zbPg=n=TZ>yzAZ*<-ueXBBG0q+t(8_mK$(ug@2B>b3(rJ%nlnxte~T{`_Epm<@jjm)C}$E<3GHgM$}g%<$1!6MI&jiBw;(zjgexM0uO^(Nx>xQSLt4ZWtj z@fjRxGT;<0V0QNqg2voR1dqye5-L`w&W%<$=Qj`}7|gFh-n@nf(wKu0^LZKBK(gDL zhqudBGI#I0e!e{;wacgNH1UkhiQ^?WX}l)GI9&feB;wnl0Oi%LT1ckj>Q}>cymOuH2hl_SlfWItnP;2sq>=_ z?wS95-G!jxHFntJZF)HJN9A6#FO&P9c6v^EcQE>6Dq1Hit@EyxyHxG0_l)mSJ4qB> z^=jO+V}{C7Ra;)Ea>Fc-Wa06g*#?7LkNI8;2pZUaBId*>@tq$5L;cRPNX#WVPE60p z{t7?8`o<=gkTYyMy&5;0|B-jfYr?InV~AVYAR1^0E49ST)U+6KhcGj>q6OJf7^b|= z)S&HEt(sj>G665LGa5GMkkp09yASVHkNceOiR5c#-y}%V-f;$y8+`h(xGBzR?1F_P zJysBH6Sf{)b*8R!!mV{8Z8;2;Ss7~Is=DVkbNraKX_l9ZN68%Wt4#VK)f-fQak)2n z;4xN)rYH!?z}B!!#F(Pgqx3NwYMtI%g1<-R-XVVis>e^Q;N+=ukv#=%r5{h_-237e z=B>CJILhCCY16B$I@nc%Cwu0_YH~Ngjjq~o9rV>Y>4lzl5$Wr%h7-Kr=>6RFv9$S# zbz+tgB{{ZR7~ei6{$^vpy0~^hu(_QXt~Pw#0=#GoBx_lEO@_q2(Z?mr^GVTBixWA$ z*U!^K^FOs|bRC+kZHeacX*Dalg*u)f{ANPtmSv$Wk$a>F z!4@-1yP3G`CZE(PkG0D;ZcZ%C&BpOw512$ML7iAFKznm{}$4h)4(Sq0ua5?!;|F#H0% zFh`6I7Dyx~@#W18$tV2Qm+Joc)?OreaDOJpU`VD&WB5_qul&t7*L&r!SKnEUWP^3U z{EnSn=K1sePj4O^oeC~{bGy8yE;DqL5LPx{mGH8)s&+CUMU9Xg&2kr~Zg*_X{nNa1 zDYuwNC@`4)e>l4CXtvw;9bWnx?OQWSml0|t)NHAGQB;HyBqR}S5hIEksZw2v+9ilt zBSaA~LV_q=C<$64u}X(cm(|ks{yyK|IsR~Rj?c;C^E}Ue-`9Oz*By}=sLOgh>nGT~ z_G#^v7Xss>1fsWY3aVE!w?&R^E3Yor%PD8Lrb`*A(iNk;b2-{1FK8VXfvi9 z2M}#nC-59C;yoC+&J#s94kbkhi7-ksDAA6x1p6UW?1?9&@Wgvt2F0u z{uv_tYIY`Ou+PzJP3@~ofceHt)0Y;$SWt#T@$BPof*V)1!n@<*f#|{cw)$Fk=`}gD zueYDy#6V~!sGvb3?kpDa3j4?j>X4mhfa2i8mK)Jq*Cs-FZq{T0FyKUY9 zIL2`?92$QM+~H34J)&^R`~qtVpeCH2Y;q|2Nmn)dWbV6ilHBV&N3oH zhWHdF$oQNGdXyo~h@6y}503kdr?p}Ebt14fT$_^ICjyG4J z5gzjGxKI|IkRiq%S`V(KAZqFd+H+0=Ot5)Z$I;4-j&+%>W!`C((-Cm(X)+OB#1V|H z$IL~)ymc*t&t7lzerSe=@oPyUbf3Yf*EMf2NDYE0^(hJ#jINt5r{>nB5LqO8xr-KK zZCcO}rBMwXCtq+YDH$W=S7IudKczHXDq?@0R3P1XVP||Xzn{>J($Q~4>&SX7!FRN zxpw}RQb6$dCZjk4b=|-!c)=Yu|A0%U?wFH{g@X>r;3WfJCvw2Bl6B_Pr3wE=mJpsf=-w^K)4F|>4NPY%;~ zNT2;S4n;-mq#9fui|#Io<$&%o@Hk7V5Z(+w5E*Lb<)aRdEYwidKu=yA8g6+Q@gkGN z%hWi%m=7gOUlIx#2e+<9(;2htsOYXDn%H0N?_aGX38tKqxE3Cz4 z+1h2P_L*H{hrT>kGXRw}2oP~BVwQ?)s9t?*;n{s9;Lxxy#a;yCf=&!Va(_`95!OoNvssq(D&lJ)dNcxBu2P8OPk%t1(smWsIBDmL zMlSUknl7Kc4)Ai{_XQk!Jehz}qb+6!A)@eMkGxagI=z|c!b6>iy2Rej9DSHby1>ti zqEDFRV?xjwC_E*R#>5AL*t2+tGP;uy>Aq0CYwDiKwQ!mZ843i8qy<&U@y#`eQ11W+frMJ63-d6gNd;g)pIpAm=)B%X-n5JV(Vf_o$AQBDL z<^*PNjBV#Gp)!agA$WQ94mGbxj(%$a-2=N4n9!{1?{8H3atv(#abxvG$qUocTYy%k zpfHiI8js?m=Dv5W-wb82ml&dSnrFTn^r^|9hL56OzkC;7%>(PgrxQom)@h^=CZFwz zh(Je%Mw)lGGX2MH2wF!(3<}9kTys3~)e+XKd&P>5zWLCA)9@@dg-SD~&VIpmnUOk! zu+L|pL>|rEJ^kt7LC1xv$arz=?2O5}6HYROjzZK*C}3N$Z^mtkRHXGIBlRv^p#YKe zDa0_BI}&#mZeAVZ=&RV?9m6}a1R2Z=s;*ZDuQBF6H~iS)vum~QMMSx`8Ozv9oGU>M zq$i7Z()hp;U%|tetz51ys{&nD1%~Swcs&oe3f`XEvF$9g*W`>VoF zZx^O-v>a*fGyM=C6Fza|Lw~!`NNpf&u8mG=DB^Sq?$G45=qOkFL8#bZvJ4~zCW^-~ zh%nSh==7W1Q(0~vDEHbb%1Jl`Q;^}p!HwZw=facqb+2!?4@W*RfBa~FxZ}LSA>Prm zrMKmZ`$$3PdR$jk?b)?+jzI#<&#e9U8VSyoJ>s!mi<&21B{g-*mxqaaphK=WoDSnu`17Q3*P&R~q zo(*<_%F)zNbYG0WAqe8vZ(nGuF2|mo35u!~th+@k&)K5b3|FqruwRm&J2FsE-PX0{ z#dlmn7z7NBp^{8bZv_lJ66-Tm(~Z`(&cz`Zu`%m)#+`H$XY_fRb_EL+EaP}b6|M|d zw5G}7jal@lIss*sB;->Y0xL$?lYIs>)E%@>5%8xvN96qm6M$`8+2zUCqW4S5Nxk53SOJ(2*IJ(Bc@rGXp}@;NUGh{ z0Yhat26lTC!|lFs!HVdkPUU*9tVIrb1aE>=h7o5&@pVSc=(2NJA_|!Cw#|C{}eo8V^Rg zOB7+*Lh19G$zVQB2P5LwzW z)Th7HcfvftbTHeLsij)X2Wk<)^lVTF$91|%D>BgX4QI(xTJ|I)%TjwL7`=i8?)4#0 zHh31~()t?cAQ?(XqA3hc+f~D2g2>lxX2<8P_Qg^~pc5x>gXXj6j7Al3c})i$dSthsiJhB84_(e*c4vBN_g96LeDsG>R1RD z_Szlcx|x0cri(I(I5cnsLIfCV7}5El)&9-Mq4%Z%`+W@no)~)MTr7^>kdGZ*CE1F$ zf>W#{q1r++Hp(I@#vD;LgC0V|YU}b5APLkxS;edlBbe*7F5M2PKH}EPNiydB6PXJL ztPO#9%*CVF^<#GQ8-g7`JEf(C74>Yk7EQcklbkH7d|2xM4iUma1Y+5*-GzMe_AfaO z{AEo^#nsZ(w6IEFqXbA(ugJoZmRE;TD3ONgd2|MN>Y7FyBP^CSeU}iZ*=z-B8dHH- ztGM2&wEEw(*pwQlpgJT-TU#Um%DiXYS1(UPx713Z+FmdqgONjvhJYN^U&SyzGASc; zmB?~sbr+O;60UNVO|Bx@V(P+)F7a!lGogv}OL#tW(o!PcCOy61NUPeOEuhv} z7hQZMXzlHb)DKS&$hRPB1nl=`;DcJQI0SI>(6Lx3jV*7ZY3nJkoGlLeE3l>t#-_}K zz{-uI>hho<1I5Dn@hmKwY6u>kqK8`7{kbW~j8y82Jl&ibmvK&Uei$1>$FaX4LRpNU z3L49jFI;h%z?@8&0q7J~_6Q|g>a!3U14nGgMi8fq5}Jhl$Ov7b1EMMgff))8V8*XS z4%4^fmHE8suxTNC>!q&iPG1@W)+uPK6*FW`WwTbuKR$y$1Gdl}nTX zAot7JhPpIsQDZR8wT|BwD}<^uB4-)J!(|K#?*>(Y21JDASRMn(iJ0s2ra6YCF`LhA z644Ac9Xs~}k9uoGucg)0U?mdswEUDSq#=RUq9X*?Kv*4Tma2uN*55%`Yxo)DD8F`* zQNE*NB5_d{x)emezBQP0Wciq>eV!<;8VHf=)t^62Akgb@&6+w*nXDF!^cAsW5h!>x zPY#_I$|`qY1=5n`^Td-OaAja(l9Yq1qUc70{;OE*a&PYP3-cCHZWXM}BRERHV$5!@ zM)7GW#AF&>n_wf6Xn7|~BU=f8V{xPqb{4x9jZzhnhd55DLbS;)GEztpOLK(&ODz5Z zhU^%#_d!V8dWJS(OJ}S{<4<+DVG~#=Au6B>$n})g9E1j`1P1;uI7Cs=HApx6cu2s5 zYJ`DJLZX<94Z%HG>fkHl=5ld}uMGV3<}gSY7sBdV5qxgz`aFy6WTLQHIJ6=L3Cn^F zKx^y|Kw#iW2^fdP`O87HaByyl1<{tyg~-T(Z0zf7)YC`*;G)grmT1{dBmC@QhXHkFek_{45STJ56^bkAh{y4P>uc$ySZr3Y zQH{J-fvSzAOsZ)7s74J+LIKUMbDi-rIy4@-mgyA@G>N zTneu^BpJLO+je7)5gc6^jeV0sb7|r#140#oi&r9*=UT@_>7W8>Bi8$>Y~)n_G8LAI zm$OOH6oFXnNh>bD%x2gQknIwi-=+sCvsXL2qE?;0U^~OGDTs>8+K%_!41|@2wCod6 z5-=?X6g$_5r47bZ`^YKZJt?9tQX!TlB$E8EoFh=&>$~f^*3CQ&h)^dw0Kswn5yIo9 zZle=kmDWmi9H+EKDnO5C(+}yX$xz9V%feMHNaEN-U<5P-Ph|h>k zxv_&w9e74}4JGr;&8$sRUh0lvK@&*znT#-qEWWiv4p8h7;|wxK1@Mqo9D0TkC76Ee z6bxhs)aTQ3{>n0b2uV%Y0Uc#L(kc+fx>hbG*E?-5uL5#(Z1uFdB$XvBl4Wsi;K)Lc zkX#;7m{G^B7qmq)h+l5}4@Sz%i;~DKOpt|OT!#XX4o1ST5qB3@7=}|0wPfqZ8Y)AR z#r-1-Nl1`LY68@f{P(cT1yf6Tc|YAkqd-2M>|N9;*q(4&zrm3NueiEvSi_a~HB;rQ zN$&2tdA6F=^@!J!S#(+1TCt915WEB?CMMz%uT1`H>7(Q3Q;<6rjs{9abZY>PKldHG z+7(6}bHU3|wEY!52PG&=WLPauQj|SnTbC*rvxMHY@xH!VC87+BEF6&n!9#;}ij=dC zpAs*<4iYAhDA|tY-$~Q9Gy4KMY6vx5Vs(=DlhK{R~>#F%ay+MJl3`r8oMp;YR z%j~m_m@tGVYAgIS#W44woa$doNs;LQ$v`4&j>+bcNYNy~AI7^_utTz=&WZ^e#KXxH z_x&^O98Xd9C=VUqkdL&sbhYv#jVUXq$-v_W5ORN=_P1$^O8$E=eHrL&!xF7$d=UT$ zw~n2oe2EpzAg_dyQ3(kNg^3^tdmKNs(A4JOIxWiPmnTcuD8)R?Cfv!(F$AT$i1Yyr z3+1Z4L_oU(l2dPz2u6gg%-j$(u%dylRj%XEKKe`r5};xYhBLHb{6uv&AJ!@#(&Ea4 zT2{!^z9_>#74fPnOptexJYn8bi)Hp!Y`!p*0)YWZVV&+LKA+#&WlW;8S)puE7pz!T zVIj}bHmeiu#FuHHP-bkgI7@K}R|m`q-7~8}m&jECC*vno{BmTxR)lBV_gn)EKtk{< zGQBu}5JL*xUhV9R5;QbC)x<+~uC0=)KM7e+SJ{vq`!y3JY0qav zBAP?F#5DkNrCDjJ%cPLurIKS22{QVk70QspY>8A)zS~k{dcP%9G|^TR#^-bRVYs;l zjuG(7xNzcYv6RA+^78nR!^BirPzAlby2u402NvnbN?)cJcOfyJgLkb&I{de+d-4J~ z9)ruJK2T7TD^e2|!r=hEE`rbBNclkeAiA$cTGbIQZRrBT=Qd**+G|s`E$B%r2@!_$fbvcT=s$>5>V>ERLu~|fxNdU>)j~Y{f z2oKl;1Y@fif;OV3%i$_*2-(N6942qakf)*OQKLm#ZkHel>?#p!s9G7+iDaJu0?YBF zvQ*QgEW-4G8N?uH4SN<=CupO00qwvR^xEvWsPLx<5r7izZ%N^!j8M9D3>0U4l>e8l z#$`2>3S6wo{-yX)<7A;r!o7VqcSMxq7LpSrEQRA|aX89)Y-cABwS%w>W28^2rm&i! zp^U>h1e!+Wv!_|aSs42+Ny|`1qYeZS%P!;@;O#4HQgab^vL(dsT0{VT2;^r-TMmbz z`}sQnn6@#-!lQ!3ZM8wovZr%STCy1qIskd0o?jQr;0w{U;kju9DT?I~T>QE99V$p> zpFL9K?;*rKO9@-md+4>bhR%@I%Hmddoiqdc+*O@xJiIWgk zQ2kIc1TvWHVr5uZ$Vq|LTul_xmW0%kg;18qb?s|FLcu6-1JFYOPy`%47{_6IEp{kL zGgQ@!{N>215U%)TpHapnd%7Hq{}h17*^uFKQW}x@uutmofbRD>U0I4NB~d4I3!^Mt z{uhGyd=~$unzD{R6#{&-JcC@8h=9D$N5@rF#&KyJ>N-NI2r-61{hXqwJGqc-Wf8U0 zDZJQJ&0(|fei3yCSun`8=5JmPpx&U{w{~{vwnfwb=i=a`S(r$a&m}$`><`A+$oPq9 zw(>{Q5FtbQkPBVL-8t>~kZjeg^MJQLkb6up2-{ z%K{usSb^??=Ykx2u*roEBaz~l<0%f39#}bgNNUG0#JKzCYAjckU?5WU@^k?Zg&f2w zCuNke>2-jCsMY2sKy<=6;Hr1J!f>OX*B`+dGxcx0a(4#v? zzc{f-mFPA_$O|`&y%iY;vac#1%H5Y8S|iFqF`vB>ZkuUz3XxehCBOGi_dj8>A+tTM zeka}U4usm1ZHe-XdkmrqC(wZ~0qnQ1Siyu7E~IG8!<0<80?iZ zS_rl_#JBV>Jn69c;0uvWB{Mspt&05j*r(d)pq%vc3b zICcYrOT*}>z2@~%k%bZd&xy}86BEVcw2l26 zswB~)(_?TwGI;$_=);hbjglqpY{d&#i^zAoR1CN-ccfFLv}!B@l!c#J!hm*&cmDr^ z$43r~Bgcsx#_;29lK0Po?#L-q^XwX`ZLxe9dpyTH0`=*MU7LQ%2TL$qBV551p&9IA zla&XO-k*%S6eqBh0Lf#!PIZocp8euM7{!Gs7p*S2GOcYKvZKW0MWt=!P;GEgbZrQm z>>XKZJG&jNVOR(PoE<^AH6z;A4&-F_js)u=Pm3^+CJ0;c+3uk@vCCI9hFZ0dIiA36;bSN~^w!>Ji#crscVdNT}BJ^KwoKIAtH0v{V(8`r$O%C3V9#PRbTIwd2ZBqt$mRZ8nlKR|OIncT z+@kD0%2WuAC7s!A8Qe&8>`w#k7C^iwLF^&lQT5ABZ7nm-0@gMY5*9l<;pAP6BiZvY z*#>z&L0RIe^}@A6uH;lUIOC(@5IPSNTs08`(!_ zvz4cLS`W?_tgKGR*e4el2)WzmLV@w)p!iXXNDwtkhylanzhGwpml&gQzJu-+VM}s_ z$dCjGl_x4U>KfnB8V_?}p#DPW9Y3qI?M3zXT$U29Nznv3h;W5Osc}o7a**!lw9qyH zewaXTLfnN^pdwb<5D8GZsE$(*p=2Bu905WC-2?ii$EH>d<7E4S0bxK4P$37>xFiJ5 zS=y8k(gYAs_SzRL5D>%AEbRCl8)31#U>i|Sxl|W+1KZeiNdiZ|B!nJqs6oec_?bo7 zXB)twupItsCvEQY z_d2X+IjG6TN-SQki3S-VMX{&HUpYqf$}!gVFY!V++S4$v`Lp_^$ipkx0>BQ0`Whqx z)y#poh&>uwfR@{`U047L^~L{(8F4L7o0|w~vbI)TxP!D#)42wukzQ{imeFZ?jw?Oj zb$6T*yFN$haZCDCEHQ{;>PMXh9FHZ2ErlfZ9>;T~=+<>JjId}A+FLk1C=i3R(v-@U zvIn)wI{Z_V$2f%?;2KHlA#w|=TVJz6VDP-T$d}@PR-s_9oCC6QsZzxifJF3$7UaZe zNBN@ z7l^isrK$vS)$f25+m<#DD64DMu|j|xFE%V1n--cXcSl<@TUrDd5{0S%T*2PC_V;0~ z1FHT@wMGFZ7|me0W1h!e0kjANjp$H6iB=ns1k)ZM>Hk_1vV^+Ujm~re1!MKPJEs+v zYeS{U0H%)WG882pVCbe3wr-;6t32_|m+;(dV^TGxZu-3B1SaQDk3Wu{o>-R!N))ja zw-noZBYekGdsYj*egjBjKE4*zXxWRZC)nHPX(GS_mkFaY^-2>6tnu*HRVAcHguV}g zPA8#P&y~g!9X|w=WE($T(5{bn_iXZ1-iN+({8YB3FnDcN6gNf-!<*T%qRMI3NJ4@Q z#8zI+U0!`%$7A14X9&*lrTNfnw`zzDtSuIRXZM{dJzE_B8CGVCqO#)4o9*v_Ko*h0 zT#)r_t839)+^O#3_BVWXe2uV6vbBMPFxXZ+mPd2~0&5*Wgzx2xLdh~f2FB;N+5pT8 zKOYIvI}y{R6^I`oFOz%ERxBm)_Oixqqyt2~7ro|dNeVkE&*O>pX$9$L-LPjJ2BoRXCfxgcd#4K7^{ziNF~PR-CYB3ty_or-3NPyDkHd87X)Is4!ZrdpZ^0r>US-z!;xj7OrBm64|-pa0jX?`T4C<$odG@?-c^iwl%vfHU-R~C z-U4f{4B6FffmP~vAH2y_voPIwkQwJYUnZ|KQa?^K1_K1$_2|hd!naeCnA=w`nEdaf zn~5n4BLoV@zY)GeRP@w}g9@B7}G99rx4xxTusF4()V_+;N=hTIuPXX6t9lAy|WpT|6Wxd@ksS9pr2gJxC!4KEH4 z$y3cnTDbXMVQU>$^K~@_r$M{bx!rvorv@8s@$s@hNoBJAOeDV5+cn-dgK)F-O`Yvk zq-}uhVL}}DLyOCTxz+Fw@t+x=4Y#9Cty79#{YdO@I6C}TXY1J*lgh00;SHri#x z4(DC_u^<@iy?326J>4H%m5%-qz4Me`mR{riMkXUW&n(8+ALt1VgzF08Zd-%HKjQcw%maMMcd^%-7y+?e^ZQ%^@vXS-AHq0jBm z`Li-7H=v!zL&OQ1lOHAsmHc^%+Ep%YGjunwL3_FK z*3mt|MNuUOP20t)vA1?XRloNUr9JFRjZU6qS=4)ydlP#}Mp)GN)!@boxTFTYLAd{x^#rTAb4q%cTkNI0>FMl=o6D5(NE75aI zuHtpVLxr16)y=@tqt_@G3Bej2!DsXmo4*pl^E__q2jbrGObKB8#KyzLHi9ic=X1#~ zKYtANALu@1T#QC_b^KxxH^LID8F7N zo=Bhf7`*)ZxK8Wkc}<_wT?Gs4izk0w@%nR2um4x)Z}~H3r5YDUb??6*`EG+dWHO{E zZW&aEQk>GwLR#+c`!N?q2_1HS_S}3@sz!q}D;?yJ81>KEChwfHYnZ%u-G}vBnLk<2 z;=)>;Kbd`~XN}1!F|U(2pK_??hqAW3<2yz37Hb|)P95rO8*Z>I?)LDO_=Kz)MUz%C z%{ZAB+J?dV=#!Z;xug$v&6>|jX;i(6dD{KhfWH-QclLk1K4e8Kr7fJed1eX~8t3(| zmhAKN{_EFmr!rvL$)5|CZJOSo^53>zl(oq-konG&0b6v?VfnkdfA2XDjvS1z29q?HZ;EKb8ZN%+Nu8R36aU%B&6vmHAClS>$Yt$5vpBExKdxKT8<0g1afuyNpufM+cJs0i9AO^4Z0cQqTH>FVf> ze4$JPD|~xoy>&fL8ya{anY&rCkIr(OXg=c9^9Aa7R(AyK`BQ1(qVDb&ZJiS@Z)JFG zC(2q?QB!SW&2AK|U60(QFM0cePxZ|4^p&e?D94~zr=R3{UN?AJe9 z@!opW*007c;w!0%zD&74_as_>b?vKv*)wuhBph8fkj$T6I}?Wd`z(YHEN$2%W<)W@ z0Qnz?iflNo4WI<`nzN-Rlujn(qrWN4t3UHHV{^NDpZO4q(%vz7vWp{L9>t4Oalxsb ze;4`0)#>Ee$`3d`Y5kK;NW1^rKK(cEPysFXy|2@?ucc0ylmn_hkj^v97exbNf-pNn zj~hGiy@1Z;dj-W;{*aF;ZO~Hgr649f%NDtZ z=oRK?JzaOtIv<=TBpyAq`ltWG>6Fu5ok^kI-v3&s<8Y-)!S8F>7n?tr>-3dUZymd8 zbG3SQq?%LlA!r5P`0CcgF^Kty!orVKZ%49H1MFPxWfN*2L^CU*)6R2@^wE z^`rK=M$HO&2Sa0*qTWq<|Dx~+-}9y>H0r00My!(c^^K%^TN-H}E)Rb;m<&cZ*fixT z*M7VpOHTuvKq?)d_U?xMepwxT%kQdwQ<$vie;^;XB$LBVK|Nd68^`zQx3kXQ-?+LV z8QS$W`Kjmh?R_R974j7Yr>duXD`g4c>Se;~sb9#5T7pD$fchoAcoRP$o=_wV7Z`anCsG@PZQaB}?J4Is-5e%6N&Up3A1=%yz@MG&e@ij#{zq$X z*R>O$FNg;G2YRCRO503QTdL5Pt2r8_fKMFLesy^fQ(>@ⅅva?(R!f8j3Z@z8&CW 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 z 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

eP&NH=>l^7^@jX^laMaZ`8%Py!CtE|c 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%0A8^!hb#3A>g% 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

k7xEK#wSrglZl($lPhtb!_M6bb%bRz1o1s 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

E#(>VW7%IVa=f8`(+`q8%k1FsIy% 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

-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 Qc{{X+Od}RAS{5{{b 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 LjxX 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%0Az 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Ðl2N}l289kkJuw7hFesaiOOIabL$ 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 X>s&vbF9bT^U}NfNH|#WF%4h%CyrA3H literal 0 HcmV?d00001 diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 0000000..bfe8a87 --- /dev/null +++ b/bot/__init__.py @@ -0,0 +1,4 @@ +from .core import * +from .handlers import router +from .middlewares import * +from .filters import * diff --git a/bot/core/__init__.py b/bot/core/__init__.py new file mode 100644 index 0000000..a3d3c93 --- /dev/null +++ b/bot/core/__init__.py @@ -0,0 +1,5 @@ +""" +Модуль управления ботом +""" +from .bots import * +from .webhook import * diff --git a/bot/core/bots.py b/bot/core/bots.py new file mode 100644 index 0000000..4090df2 --- /dev/null +++ b/bot/core/bots.py @@ -0,0 +1,398 @@ +""" +Ядро PrimoGuard Bot: Инициализация, Управление и Информация +""" +from datetime import datetime + +from aiogram import Bot, Dispatcher +from aiogram.client.default import DefaultBotProperties +from aiogram.fsm.storage.memory import MemoryStorage +from aiogram.types import User, ChatAdministratorRights, BotDescription, BotShortDescription +from aiogram.utils.i18n import I18n, SimpleI18nMiddleware +from pymorphy3 import MorphAnalyzer + +from configs import settings +from middleware.loggers import logger + +__all__ = ('bot', 'dp', 'storage', 'i18n', 'morph', 'BotInfo') + + +# ================= STORAGE И DISPATCHER ================= + +storage = MemoryStorage() +dp = Dispatcher(storage=storage) +dp["is_active"] = True + + +# ================= ИНТЕРНАЦИОНАЛИЗАЦИЯ ================= + +i18n = I18n(path="locales", default_locale="ru", domain="bot") +i18n_middleware = SimpleI18nMiddleware(i18n=i18n) +i18n_middleware.setup(dp) + + +# ================= БОТ ================= + +bot = Bot( + token=settings.active_bot_token, + default=DefaultBotProperties( + parse_mode=settings.PARSE_MODE, + disable_notification=settings.DISABLE_NOTIFICATION, + protect_content=settings.PROTECT_CONTENT, + allow_sending_without_reply=settings.ALLOW_SENDING_WITHOUT_REPLY, + link_preview_is_disabled=settings.LINK_PREVIEW_IS_DISABLED, + link_preview_prefer_small_media=settings.LINK_PREVIEW_PREFER_SMALL_MEDIA, + link_preview_prefer_large_media=settings.LINK_PREVIEW_PREFER_LARGE_MEDIA, + link_preview_show_above_text=settings.LINK_PREVIEW_SHOW_ABOVE_TEXT, + show_caption_above_media=settings.SHOW_CAPTION_ABOVE_MEDIA + ) +) + + +# ================= МОРФОАНАЛИЗАТОР ================= + +morph = MorphAnalyzer() + + +# ================= КЛАСС УПРАВЛЕНИЯ БОТОМ ================= + +class BotInfo: + """Класс для хранения данных и управления ботом""" + + # Основные данные бота + id: int = None + url: str = None + first_name: str = None + last_name: str = None + username: str = None + description: str = None + short_description: str = None + is_premium: bool = False + + # Возможности бота + can_join_groups: bool = False + can_read_all_group_messages: bool = False + supports_inline_queries: bool = False + can_connect_to_business: bool = False + has_main_web_app: bool = False + added_to_attachment_menu: bool = False + + # Данные из конфига + prefix: str = settings.PREFIX + started_at: datetime = None + + @classmethod + def mention(cls) -> str: + """Упоминание бота""" + return f'@{cls.username}' if cls.username else f'id{cls.id}' + + @classmethod + async def webhook(cls, bots: Bot = bot) -> None: + """ + Настраивает webhook для бота. + + Args: + bots: Объект бота для управления + """ + # Только если включен режим webhook + if not settings.WEBHOOK: + logger.debug("Режим Webhook отключен (WEBHOOK=False)", log_type='WEBHOOK') + return + + # Проверяем наличие URL + if not settings.WEBHOOK_URL: + logger.warning( + "⚠️ WEBHOOK_URL не указан в настройках", + log_type='WEBHOOK' + ) + return + + try: + logger.info("Настройка вебхука бота", log_type='BOT') + + # Проверяем текущий webhook + current_info = await bots.get_webhook_info() + + # Если уже установлен нужный URL, пропускаем + if current_info.url == settings.WEBHOOK_URL: + logger.info( + f"✓ Вебхук уже установлен: {settings.WEBHOOK_URL}", + log_type='BOT' + ) + return + + # Устанавливаем webhook + await bots.set_webhook( + url=settings.WEBHOOK_URL, + secret_token=settings.SECRET_TOKEN, + drop_pending_updates=True + ) + + logger.success( + f"✓ Вебхук установлен: {settings.WEBHOOK_URL}", + log_type='BOT' + ) + + except Exception as e: + logger.error( + f"❌ Ошибка установки вебхука: {e}", + log_type='BOT' + ) + + @classmethod + async def info(cls, bots: Bot = bot) -> dict: + """ + Получает и сохраняет информацию о боте. + + :param bots: Объект бота для управления + :return: Словарь с данными о боте + """ + logger.info("Получение информации о боте", log_type='BOT') + + bot_info: User = await bots.get_me() + + cls.id = bot_info.id + cls.url = f'tg://user?id={cls.id}' + cls.first_name = bot_info.first_name + cls.last_name = bot_info.last_name + cls.username = bot_info.username + cls.can_join_groups = getattr(bot_info, 'can_join_groups', False) + cls.can_read_all_group_messages = getattr(bot_info, 'can_read_all_group_messages', False) + cls.supports_inline_queries = bot_info.supports_inline_queries or False + cls.can_connect_to_business = bot_info.can_connect_to_business or False + cls.has_main_web_app = bot_info.has_main_web_app or False + cls.added_to_attachment_menu = bot_info.added_to_attachment_menu or False + cls.started_at = datetime.now() + + logger.success(f"Информация о боте @{cls.username} получена", log_type='BOT') + + return { + 'id': cls.id, + 'url': cls.url, + 'first_name': cls.first_name, + 'last_name': cls.last_name, + 'username': cls.username, + 'prefix': cls.prefix, + 'is_premium': cls.is_premium, + 'can_join_groups': cls.can_join_groups, + 'can_read_all_group_messages': cls.can_read_all_group_messages, + 'supports_inline_queries': cls.supports_inline_queries, + 'can_connect_to_business': cls.can_connect_to_business, + 'has_main_web_app': cls.has_main_web_app, + 'added_to_attachment_menu': cls.added_to_attachment_menu, + } + + @staticmethod + async def set_name(bots: Bot = bot, new_name: str = None) -> bool: + """Устанавливает имя бота""" + new_name = new_name or settings.BOT_NAME + + if not (1 <= len(new_name) <= 64): + logger.error(f"Имя бота должно быть от 1 до 64 символов (текущее: {len(new_name)})", log_type='BOT_SETUP') + return False + + try: + current_name = (await bots.get_me()).first_name + + if current_name == new_name: + logger.debug(f"Имя бота уже установлено: '{current_name}'", log_type='BOT_SETUP') + return False + + await bots.set_my_name(new_name) + logger.success(f"Имя бота изменено: '{current_name}' → '{new_name}'", log_type='BOT_SETUP') + return True + + except Exception as e: + logger.error(f"Ошибка установки имени бота: {e}", log_type='BOT_SETUP') + return False + + @staticmethod + async def set_description(bots: Bot = bot, new_description: str = None) -> bool: + """Устанавливает полное описание бота""" + new_description = new_description or settings.BOT_DESCRIPTION + + if not (0 < len(new_description) <= 512): + logger.error(f"Описание должно быть от 1 до 512 символов (текущее: {len(new_description)})", log_type='BOT_SETUP') + return False + + try: + current_description: BotDescription = await bots.get_my_description() + current_text = current_description.description if current_description else "" + + if current_text == new_description: + logger.debug("Описание бота уже установлено", log_type='BOT_SETUP') + return False + + await bots.set_my_description(description=new_description) + logger.success("Описание бота обновлено", log_type='BOT_SETUP') + return True + + except Exception as e: + logger.error(f"Ошибка установки описания бота: {e}", log_type='BOT_SETUP') + return False + + @staticmethod + async def set_short_description(bots: Bot = bot, new_short: str = None) -> bool: + """Устанавливает короткое описание бота""" + new_short = new_short or settings.BOT_SHORT_DESCRIPTION + + if not (0 < len(new_short) <= 120): + logger.error(f"Короткое описание должно быть от 1 до 120 символов (текущее: {len(new_short)})", log_type='BOT_SETUP') + return False + + try: + current_short: BotShortDescription = await bots.get_my_short_description() + current_text = current_short.short_description if current_short else "" + + if current_text == new_short: + logger.debug("Короткое описание бота уже установлено", log_type='BOT_SETUP') + return False + + await bots.set_my_short_description(short_description=new_short) + logger.success("Короткое описание бота обновлено", log_type='BOT_SETUP') + return True + + except Exception as e: + logger.error(f"Ошибка установки короткого описания: {e}", log_type='BOT_SETUP') + return False + + @staticmethod + async def set_administrator_rights(bots: Bot = bot, rights: ChatAdministratorRights = None) -> bool: + """Устанавливает права администратора по умолчанию""" + rights = rights or settings.rights + + try: + current_rights = await bots.get_my_default_administrator_rights() + + if current_rights == rights: + logger.debug("Права администратора уже установлены", log_type='BOT_SETUP') + return False + + await bots.set_my_default_administrator_rights(rights) + logger.success("Права администратора обновлены", log_type='BOT_SETUP') + return True + + except Exception as e: + logger.error(f"Ошибка установки прав администратора: {e}", log_type='BOT_SETUP') + return False + + @classmethod + def print(cls, to_console: bool = True, to_file: bool = True) -> str: + """ + Красиво форматирует и выводит информацию о боте. + + :param to_console: Вывести в консоль + :param to_file: Записать в файлы + :return: Отформатированная строка + """ + # Формирование блоков информации + header = f"╔═══════════════════════════════════════════════════════════╗" + title = f"║ 🤖 PRIMOGUARD BOT - ИНФОРМАЦИЯ О ЗАПУСКЕ ║" + separator = f"╠═══════════════════════════════════════════════════════════╣" + footer = f"╚═══════════════════════════════════════════════════════════╝" + + lines = [ + header, + title, + separator, + f"║ ⏰ Время запуска: {cls.started_at.strftime('%d.%m.%Y %H:%M:%S')}", + f"║", + f"║ 📋 ОСНОВНАЯ ИНФОРМАЦИЯ:", + f"║ • Имя: {cls.first_name} {cls.last_name or ''}".ljust(60) + "║", + f"║ • Username: @{cls.username}".ljust(60) + "║", + f"║ • ID: {cls.id}".ljust(60) + "║", + f"║", + f"║ ⚙️ ВОЗМОЖНОСТИ БОТА:", + f"║ • Вступать в группы: {'✅' if cls.can_join_groups else '❌'}".ljust(60) + "║", + f"║ • Читать все сообщения: {'✅' if cls.can_read_all_group_messages else '❌'}".ljust(60) + "║", + f"║ • Инлайн-запросы: {'✅' if cls.supports_inline_queries else '❌'}".ljust(60) + "║", + f"║ • Бизнес-аккаунты: {'✅' if cls.can_connect_to_business else '❌'}".ljust(60) + "║", + f"║ • Веб-приложение: {'✅' if cls.has_main_web_app else '❌'}".ljust(60) + "║", + f"║ • Меню вложений: {'✅' if cls.added_to_attachment_menu else '❌'}".ljust(60) + "║", + f"║", + f"║ 🔧 НАСТРОЙКИ:", + f"║ • Префикс команд: {cls.prefix}".ljust(60) + "║", + f"║ • Режим: {'Webhook' if settings.WEBHOOK else 'Polling'}".ljust(60) + "║", + footer + ] + + output = '\n'.join(lines) + + # Вывод в консоль с цветом + if to_console and settings.START_INFO_CONSOLE: + colored_output = f"\033[96m{output}\033[0m" # Cyan цвет + print(colored_output) + + # Запись в файлы + if to_file and settings.START_INFO_TO_FILE: + try: + settings.LOG_DIR.mkdir(parents=True, exist_ok=True) + + # Полная информация в bot_info.log + info_file = settings.LOG_DIR / 'bot_info.log' + with open(info_file, 'w', encoding='utf-8') as f: + f.write(output) + + # Краткая запись в историю запусков + start_file = settings.LOG_DIR / 'bot_starts.log' + with open(start_file, 'a', encoding='utf-8') as f: + start_entry = f"{cls.started_at.strftime('%d.%m.%Y %H:%M:%S')} | @{cls.username} | Mode: {'Webhook' if settings.WEBHOOK else 'Polling'}\n" + f.write(start_entry) + + logger.debug(f"Информация о боте записана в {info_file}", log_type='BOT_INFO') + + except Exception as e: + logger.error(f"Ошибка записи информации в файл: {e}", log_type='BOT_INFO') + + return output + + @classmethod + async def setup( + cls, + bots: Bot = bot, + perm: bool = None, + setup_webhook: bool = True + ) -> None: + """ + Выполняет полную настройку бота. + + Args: + bots: Объект бота для управления + perm: Разрешение на изменения (если None, берется из настроек) + setup_webhook: Устанавливать ли webhook (по умолчанию True) + """ + perm = perm if perm is not None else settings.BOT_EDIT + + logger.info("🚀 Процесс запуска бота!", log_type='START') + + # Настройка вебхука (только если разрешено) + if setup_webhook: + await cls.webhook(bots=bots) + + # Получение информации + await cls.info(bots=bots) + + # Обновление профиля (если разрешено) + if perm: + logger.info("Начало настройки профиля бота...", log_type='BOT_SETUP') + + results = { + 'name': await cls.set_name(bots=bots), + 'description': await cls.set_description(bots=bots), + 'short_description': await cls.set_short_description(bots=bots), + 'admin_rights': await cls.set_administrator_rights(bots=bots) + } + + changed_count = sum(results.values()) + logger.info( + f"Настройка завершена. Изменено параметров: {changed_count}/4", + log_type='BOT_SETUP' + ) + else: + logger.warning( + "⚠️ Изменение настроек бота отключено (BOT_EDIT=False)", + log_type='BOT_SETUP' + ) + + # Вывод красивой информации + cls.print() + diff --git a/bot/core/webhook.py b/bot/core/webhook.py new file mode 100644 index 0000000..616ceb1 --- /dev/null +++ b/bot/core/webhook.py @@ -0,0 +1,259 @@ +""" +Управление вебхуком бота через класс-менеджер +""" +import secrets +from typing import Optional + +from aiohttp import web +from aiogram import Bot, Dispatcher +from aiogram.types import WebhookInfo +from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application + +from configs import settings +from middleware.loggers import logger + +__all__ = ('WebhookManager',) + + +class WebhookManager: + """ + Менеджер для управления webhook режимом. + + Инкапсулирует всю логику работы с webhook: + - Создание aiohttp приложения + - Регистрация handlers + - Установка/удаление webhook + - Запуск webhook сервера + + Attributes: + bot: Экземпляр бота + dp: Диспетчер + app: aiohttp приложение + secret_token: Секретный токен для webhook + """ + + def __init__(self, bot: Bot, dp: Dispatcher): + """ + Args: + bot: Экземпляр бота + dp: Диспетчер + """ + self.bot = bot + self.dp = dp + self.app = web.Application() + self._configured = False + + # Генерируем или используем существующий токен + self.secret_token = self._get_or_generate_token() + + def _get_or_generate_token(self) -> str: + """ + Получает токен из настроек или генерирует новый. + + Returns: + str: Секретный токен + """ + if hasattr(settings, 'SECRET_TOKEN') and settings.SECRET_TOKEN: + logger.debug("Используется SECRET_TOKEN из настроек", log_type='WEBHOOK') + return settings.SECRET_TOKEN + + # Генерируем случайный токен (32 символа) + token = secrets.token_urlsafe(32) + logger.info( + f"🔐 Сгенерирован новый SECRET_TOKEN: {token[:8]}...", + log_type='WEBHOOK' + ) + return token + + async def get_info(self) -> WebhookInfo: + """ + Получает информацию о текущем вебхуке. + + Returns: + WebhookInfo: Информация о вебхуке + """ + try: + info = await self.bot.get_webhook_info() + logger.debug( + f"Webhook URL: {info.url or 'не установлен'}", + log_type='WEBHOOK' + ) + return info + except Exception as e: + logger.error( + f"Ошибка получения информации о вебхуке: {e}", + log_type='WEBHOOK' + ) + raise + + async def delete(self, drop_pending_updates: bool = True) -> bool: + """ + Удаляет текущий вебхук. + + Args: + drop_pending_updates: Удалить накопленные обновления + + Returns: + bool: True если удаление успешно + """ + try: + result = await self.bot.delete_webhook( + drop_pending_updates=drop_pending_updates + ) + + if result: + logger.success("✓ Вебхук успешно удален", log_type='WEBHOOK') + else: + logger.debug("Вебхук не был установлен", log_type='WEBHOOK') + + return result + + except Exception as e: + logger.error(f"Ошибка удаления вебхука: {e}", log_type='WEBHOOK') + return False + + async def setup( + self, + webhook_url: Optional[str] = None, + secret_token: Optional[str] = None, + drop_pending_updates: bool = True + ) -> bool: + """ + Устанавливает вебхук для бота. + + Args: + webhook_url: URL вебхука (если None, берется из settings) + secret_token: Секретный токен (если None, используется self.secret_token) + drop_pending_updates: Удалить накопленные обновления + + Returns: + bool: True если установка успешна + """ + url = webhook_url or settings.WEBHOOK_URL + token = secret_token or self.secret_token + + if not url: + logger.error("WEBHOOK_URL не установлен", log_type='WEBHOOK') + return False + + try: + # Проверяем текущий webhook + current_info = await self.bot.get_webhook_info() + + # Если уже установлен правильный URL, не трогаем + if current_info.url == url: + logger.info( + f"✓ Webhook уже установлен на {url}", + log_type='WEBHOOK' + ) + return True + + # Удаляем старый webhook если есть + if current_info.url: + logger.debug(f"Удаление старого webhook: {current_info.url}", log_type='WEBHOOK') + await self.delete(drop_pending_updates=drop_pending_updates) + + # Небольшая задержка + import asyncio + await asyncio.sleep(0.5) + + # Устанавливаем новый + result = await self.bot.set_webhook( + url=url, + secret_token=token, + drop_pending_updates=drop_pending_updates + ) + + if result: + logger.success(f"✓ Вебхук установлен: {url}", log_type='WEBHOOK') + else: + logger.error("❌ Не удалось установить вебхук", log_type='WEBHOOK') + + return result + + except Exception as e: + logger.error(f"❌ Ошибка установки вебхука: {e}", log_type='WEBHOOK') + return False + + def configure( + self, + webhook_path: Optional[str] = None, + secret_token: Optional[str] = None + ) -> None: + """ + Конфигурирует webhook handler для aiohttp app. + + Args: + webhook_path: Путь для webhook (если None, извлекается из WEBHOOK_URL) + secret_token: Секретный токен (если None, используется self.secret_token) + """ + if self._configured: + logger.warning("Webhook уже сконфигурирован", log_type='WEBHOOK') + return + + # Определяем путь из WEBHOOK_URL + if webhook_path: + path = webhook_path + elif settings.WEBHOOK_URL: + from urllib.parse import urlparse + parsed = urlparse(settings.WEBHOOK_URL) + path = parsed.path if parsed.path else "/webhook" + else: + path = "/webhook" + + # Используем токен + token = secret_token or self.secret_token + + # Создаём webhook handler + webhook_handler = SimpleRequestHandler( + dispatcher=self.dp, + bot=self.bot, + secret_token=token + ) + + # Регистрируем в aiohttp app + webhook_handler.register(self.app, path=path) + setup_application(self.app, self.dp, bot=self.bot) + + self._configured = True + logger.success( + f"✓ Webhook handler настроен на путь: {path}", + log_type='WEBHOOK' + ) + + def run( + self, + host: Optional[str] = None, + port: Optional[int] = None, + access_log: Optional[bool] = None + ) -> None: + """ + Запускает webhook сервер (блокирующий вызов). + + Args: + host: Хост сервера (если None, берется из settings) + port: Порт сервера (если None, берется из settings) + access_log: Логировать запросы (если None, берется из settings) + """ + if not self._configured: + logger.error( + "Webhook не сконфигурирован! Вызовите configure() перед run()", + log_type='WEBHOOK' + ) + return + + host = host or settings.WEBAPP_HOST + port = port or settings.WEBAPP_PORT + access_log_enabled = access_log if access_log is not None else settings.ACCES_LOG + + logger.info( + f"🌐 Запуск webhook сервера: {host}:{port}", + log_type='WEBHOOK' + ) + + web.run_app( + self.app, + host=host, + port=port, + access_log=logger if access_log_enabled else None + ) diff --git a/bot/filters/__init__.py b/bot/filters/__init__.py new file mode 100644 index 0000000..8c63804 --- /dev/null +++ b/bot/filters/__init__.py @@ -0,0 +1,11 @@ +""" +Модуль фильтров для aiogram +""" +from .subscription import * +from .admin import * +from .spam import * +from .modes import * +from .chat_type import * +from .msg_content import * +from .chat_rights import * +from .callback import * diff --git a/bot/filters/admin.py b/bot/filters/admin.py new file mode 100644 index 0000000..d5cfe00 --- /dev/null +++ b/bot/filters/admin.py @@ -0,0 +1,109 @@ +""" +Фильтры для проверки прав администратора +""" +from typing import Union + +from aiogram.filters import BaseFilter +from aiogram.types import Message, CallbackQuery + +from configs import settings +from database import get_manager +from middleware.loggers import logger + +__all__ = ('IsSuperAdmin', 'IsAdmin', 'IsOwner') + + +class IsSuperAdmin(BaseFilter): + """ + Проверяет, является ли пользователь суперадминистратором (из .env). + + Суперадмины имеют полный доступ ко всем командам бота. + + Example: + ```python + @router.message(Command("addadmin"), IsSuperAdmin()) + async def add_admin_command(message: Message): + await message.answer("Добавление админа...") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + user_id = event.from_user.id + is_super_admin = user_id in settings.OWNER_ID + + if not is_super_admin: + logger.warning( + f"Попытка доступа к команде суперадмина от user_id={user_id}", + log_type='SECURITY', + message=event if isinstance(event, Message) else None + ) + + return is_super_admin + + +class IsAdmin(BaseFilter): + """ + Проверяет, является ли пользователь администратором (суперадмин или доп. админ). + + Администраторы могут управлять банвордами, но не могут добавлять других админов. + Список дополнительных админов загружается из БД через BanWordsManager. + + Example: + ```python + @router.message(Command("addword"), IsAdmin()) + async def add_word_command(message: Message): + await message.answer("Добавление банворда...") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + user_id = event.from_user.id + + # Проверка суперадмина + if user_id in settings.OWNER_ID: + return True + + # Проверка доп. админа из БД (через кэш) + manager = get_manager() + is_db_admin = manager.is_admin_cached(user_id) + + if not is_db_admin: + logger.warning( + f"Попытка доступа к админ-команде от user_id={user_id}", + log_type='SECURITY', + message=event if isinstance(event, Message) else None + ) + + return is_db_admin + + +class IsOwner(BaseFilter): + """ + Проверяет, является ли пользователь первым владельцем бота (OWNER_ID[0]). + + Используется для критических операций (например, полная очистка данных). + + Example: + ```python + @router.message(Command("reset_all"), IsOwner()) + async def reset_command(message: Message): + await message.answer("⚠️ Сброс всех данных...") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + user_id = event.from_user.id + + # Берём первого суперадмина как владельца + owner_id = settings.OWNER_ID[0] if settings.OWNER_ID else None + + is_owner = user_id == owner_id + + if not is_owner: + logger.warning( + f"Попытка доступа к команде владельца от user_id={user_id}", + log_type='SECURITY', + message=event if isinstance(event, Message) else None + ) + + return is_owner diff --git a/bot/filters/callback.py b/bot/filters/callback.py new file mode 100644 index 0000000..ad52fdc --- /dev/null +++ b/bot/filters/callback.py @@ -0,0 +1,253 @@ +""" +Фильтры для обработки callback-запросов +""" +import re +from typing import Union + +from aiogram.filters import BaseFilter +from aiogram.types import CallbackQuery + +from middleware.loggers import logger + +__all__ = ( + 'CallbackStartsWith', + 'CallbackEndsWith', + 'CallbackContains', + 'CallbackMatches', + 'CallbackIn' +) + + +class CallbackStartsWith(BaseFilter): + """ + Проверяет, начинается ли callback_data с указанного префикса. + + Attributes: + prefix: Префикс для проверки (строка или список строк) + ignore_case: Игнорировать регистр + + Example: + ```python + # Один префикс + @router.callback_query(CallbackStartsWith("menu:")) + async def menu_handler(callback: CallbackQuery): + await callback.answer("Меню") + + # Несколько префиксов + @router.callback_query(CallbackStartsWith(["admin:", "mod:"])) + async def admin_handler(callback: CallbackQuery): + await callback.answer("Админ панель") + ``` + """ + + def __init__(self, prefix: Union[str, list[str]], ignore_case: bool = True): + """ + Args: + prefix: Префикс или список префиксов + ignore_case: Игнорировать регистр букв + """ + self.prefixes = [prefix] if isinstance(prefix, str) else prefix + self.ignore_case = ignore_case + + if self.ignore_case: + self.prefixes = [p.lower() for p in self.prefixes] + + async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]: + if not callback.data: + return False + + data = callback.data.lower() if self.ignore_case else callback.data + + for prefix in self.prefixes: + if data.startswith(prefix): + # Извлекаем данные после префикса + value = callback.data[len(prefix):] + + logger.debug( + f"Callback с префиксом '{prefix}': {callback.data}", + log_type='CALLBACK' + ) + + return { + 'matched': True, + 'prefix': prefix, + 'value': value, + 'full_data': callback.data + } + + return False + + +class CallbackEndsWith(BaseFilter): + """ + Проверяет, заканчивается ли callback_data на указанный суффикс. + + Example: + ```python + @router.callback_query(CallbackEndsWith(":confirm")) + async def confirm_handler(callback: CallbackQuery, matched: dict): + action = matched['value'] + await callback.answer(f"Подтверждение: {action}") + ``` + """ + + def __init__(self, suffix: Union[str, list[str]], ignore_case: bool = True): + """ + Args: + suffix: Суффикс или список суффиксов + ignore_case: Игнорировать регистр букв + """ + self.suffixes = [suffix] if isinstance(suffix, str) else suffix + self.ignore_case = ignore_case + + if self.ignore_case: + self.suffixes = [s.lower() for s in self.suffixes] + + async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]: + if not callback.data: + return False + + data = callback.data.lower() if self.ignore_case else callback.data + + for suffix in self.suffixes: + if data.endswith(suffix): + # Извлекаем данные до суффикса + value = callback.data[:-len(suffix)] + + return { + 'matched': True, + 'suffix': suffix, + 'value': value, + 'full_data': callback.data + } + + return False + + +class CallbackContains(BaseFilter): + """ + Проверяет, содержит ли callback_data указанную подстроку. + + Example: + ```python + @router.callback_query(CallbackContains("delete")) + async def delete_handler(callback: CallbackQuery): + await callback.answer("Удаление...") + ``` + """ + + def __init__(self, substring: Union[str, list[str]], ignore_case: bool = True): + """ + Args: + substring: Подстрока или список подстрок + ignore_case: Игнорировать регистр букв + """ + self.substrings = [substring] if isinstance(substring, str) else substring + self.ignore_case = ignore_case + + if self.ignore_case: + self.substrings = [s.lower() for s in self.substrings] + + async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]: + if not callback.data: + return False + + data = callback.data.lower() if self.ignore_case else callback.data + + for substring in self.substrings: + if substring in data: + return { + 'matched': True, + 'substring': substring, + 'full_data': callback.data + } + + return False + + +class CallbackMatches(BaseFilter): + """ + Проверяет callback_data по regex паттерну. + + Example: + ```python + # Паттерн: user_123, user_456 и т.д. + @router.callback_query(CallbackMatches(r"^user_(\d+)$")) + async def user_handler(callback: CallbackQuery, matched: dict): + user_id = matched['groups'] + await callback.answer(f"Пользователь {user_id}") + ``` + """ + + def __init__(self, pattern: Union[str, re.Pattern], flags: int = 0): + """ + Args: + pattern: Regex паттерн (строка или скомпилированный Pattern) + flags: Флаги для regex (например, re.IGNORECASE) + """ + if isinstance(pattern, str): + self.pattern = re.compile(pattern, flags) + else: + self.pattern = pattern + + async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]: + if not callback.data: + return False + + match = self.pattern.match(callback.data) + + if match: + logger.debug( + f"Callback соответствует паттерну {self.pattern.pattern}: {callback.data}", + log_type='CALLBACK' + ) + + return { + 'matched': True, + 'pattern': self.pattern.pattern, + 'groups': match.groups(), + 'groupdict': match.groupdict(), + 'full_data': callback.data + } + + return False + + +class CallbackIn(BaseFilter): + """ + Проверяет, находится ли callback_data в списке разрешенных значений. + + Example: + ```python + @router.callback_query(CallbackIn(["yes", "no", "cancel"])) + async def choice_handler(callback: CallbackQuery): + choice = callback.data + await callback.answer(f"Выбрано: {choice}") + ``` + """ + + def __init__(self, values: list[str], ignore_case: bool = True): + """ + Args: + values: Список разрешенных значений + ignore_case: Игнорировать регистр букв + """ + self.values = values + self.ignore_case = ignore_case + + if self.ignore_case: + self.values = [v.lower() for v in values] + + async def __call__(self, callback: CallbackQuery) -> Union[bool, dict]: + if not callback.data: + return False + + data = callback.data.lower() if self.ignore_case else callback.data + + if data in self.values: + return { + 'matched': True, + 'value': callback.data + } + + return False diff --git a/bot/filters/chat_rights.py b/bot/filters/chat_rights.py new file mode 100644 index 0000000..f98b03a --- /dev/null +++ b/bot/filters/chat_rights.py @@ -0,0 +1,324 @@ +""" +Фильтры для проверки прав пользователей в чатах +""" +from typing import Any, Union + +from aiogram import Bot +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError +from aiogram.filters import BaseFilter +from aiogram.types import Message, CallbackQuery +from aiogram.enums import ChatMemberStatus + +from configs import settings +from middleware.loggers import logger + +__all__ = ( + 'IsBotOwner', + 'IsChatCreator', + 'IsChatAdmin', + 'IsModerator', + 'CanDeleteMessages', + 'CanRestrictMembers', + 'CanPinMessages' +) + + +class IsBotOwner(BaseFilter): + """ + Проверяет, является ли пользователь владельцем бота (из .env). + + Attributes: + send_error_message: Отправлять ли сообщение об ошибке доступа + + Example: + ```python + # Без сообщения об ошибке + @router.message(Command("reset"), IsOwner()) + async def reset_command(message: Message): + await message.answer("🔄 Сброс данных...") + + # С сообщением об ошибке + @router.message(Command("secret"), IsOwner(send_error_message=True)) + async def secret_command(message: Message): + await message.answer("🔐 Секретная команда выполнена") + ``` + """ + + def __init__(self, send_error_message: bool = False) -> None: + """ + Args: + send_error_message: Если True, отправляет сообщение при отказе в доступе + """ + self.send_error_message = send_error_message + + async def __call__( + self, + event: Union[Message, CallbackQuery], + bot: Bot + ) -> Union[bool, dict[str, Any]]: + """ + Проверка владельца бота. + + Returns: + bool или dict: True/dict если владелец, False иначе + """ + if not event.from_user: + return False + + user_id = event.from_user.id + is_owner = user_id in settings.OWNER_ID + + if not is_owner: + logger.warning( + f"Попытка доступа к команде владельца от user_id={user_id}", + log_type='SECURITY', + message=event if isinstance(event, Message) else None + ) + + if self.send_error_message: + error_text = "⛔ Эта команда доступна только владельцу бота!" + + if isinstance(event, Message): + await event.answer(error_text) + elif isinstance(event, CallbackQuery): + await event.answer(error_text, show_alert=True) + + return False + + # Возвращаем информацию для handler + return { + 'is_owner': True, + 'user_id': user_id, + 'owner_ids': settings.OWNER_ID + } + + +class IsChatCreator(BaseFilter): + """ + Проверяет, является ли пользователь создателем чата. + + Example: + ```python + @router.message(Command("transfer"), IsChatCreator()) + async def transfer_ownership(message: Message): + await message.answer("👑 Передача владения чатом...") + ``` + """ + + async def __call__(self, message: Message, bot: Bot) -> Union[bool, dict]: + try: + member = await bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + is_creator = member.status == ChatMemberStatus.CREATOR + + if is_creator: + return { + 'is_creator': True, + 'user_id': message.from_user.id, + 'chat_id': message.chat.id + } + + return False + + except (TelegramBadRequest, TelegramForbiddenError) as e: + logger.error( + f"Ошибка проверки создателя чата: {e}", + log_type='CHAT_RIGHTS', + message=message + ) + return False + + +class IsChatAdmin(BaseFilter): + """ + Проверяет, является ли пользователь администратором чата (или создателем). + + Example: + ```python + @router.message(Command("ban"), IsChatAdmin()) + async def ban_user(message: Message): + await message.answer("🔨 Бан пользователя...") + ``` + """ + + async def __call__(self, message: Message, bot: Bot) -> Union[bool, dict]: + try: + member = await bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + is_admin = member.status in ( + ChatMemberStatus.ADMINISTRATOR, + ChatMemberStatus.CREATOR + ) + + if is_admin: + return { + 'is_admin': True, + 'status': member.status.value, + 'user_id': message.from_user.id, + 'chat_id': message.chat.id + } + + return False + + except (TelegramBadRequest, TelegramForbiddenError) as e: + logger.error( + f"Ошибка проверки администратора чата: {e}", + log_type='CHAT_RIGHTS', + message=message + ) + return False + + +class IsModerator(BaseFilter): + """ + Проверяет, имеет ли администратор модераторские права: + - Удаление сообщений + - Ограничение пользователей + - Закрепление сообщений + + Example: + ```python + @router.message(Command("warn"), IsModerator()) + async def warn_user(message: Message): + await message.answer("⚠️ Предупреждение пользователю...") + ``` + """ + + async def __call__(self, message: Message, bot: Bot) -> Union[bool, dict]: + try: + member = await bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + # Создатель всегда модератор + if member.status == ChatMemberStatus.CREATOR: + return { + 'is_moderator': True, + 'status': 'creator', + 'user_id': message.from_user.id + } + + # Проверка прав администратора + if member.status != ChatMemberStatus.ADMINISTRATOR: + return False + + # Проверка модераторских прав + required_rights = [ + getattr(member, 'can_delete_messages', False), + getattr(member, 'can_restrict_members', False), + getattr(member, 'can_pin_messages', False), + ] + + has_all_rights = all(required_rights) + + if has_all_rights: + return { + 'is_moderator': True, + 'status': 'administrator', + 'can_delete': required_rights[0], + 'can_restrict': required_rights[1], + 'can_pin': required_rights[2], + 'user_id': message.from_user.id + } + + return False + + except (TelegramBadRequest, TelegramForbiddenError) as e: + logger.error( + f"Ошибка проверки модератора: {e}", + log_type='CHAT_RIGHTS', + message=message + ) + return False + + +class CanDeleteMessages(BaseFilter): + """ + Проверяет право на удаление сообщений. + + Example: + ```python + @router.message(Command("clear"), CanDeleteMessages()) + async def clear_messages(message: Message): + await message.answer("🗑️ Очистка сообщений...") + ``` + """ + + async def __call__(self, message: Message, bot: Bot) -> bool: + try: + member = await bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + if member.status == ChatMemberStatus.CREATOR: + return True + + return getattr(member, 'can_delete_messages', False) + + except (TelegramBadRequest, TelegramForbiddenError): + return False + + +class CanRestrictMembers(BaseFilter): + """ + Проверяет право на ограничение пользователей (бан, мут). + + Example: + ```python + @router.message(Command("mute"), CanRestrictMembers()) + async def mute_user(message: Message): + await message.answer("🔇 Мут пользователя...") + ``` + """ + + async def __call__(self, message: Message, bot: Bot) -> bool: + try: + member = await bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + if member.status == ChatMemberStatus.CREATOR: + return True + + return getattr(member, 'can_restrict_members', False) + + except (TelegramBadRequest, TelegramForbiddenError): + return False + + +class CanPinMessages(BaseFilter): + """ + Проверяет право на закрепление сообщений. + + Example: + ```python + @router.message(Command("pin"), CanPinMessages()) + async def pin_message(message: Message): + if message.reply_to_message: + await message.reply_to_message.pin() + ``` + """ + + async def __call__(self, message: Message, bot: Bot) -> bool: + try: + member = await bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + if member.status == ChatMemberStatus.CREATOR: + return True + + return getattr(member, 'can_pin_messages', False) + + except (TelegramBadRequest, TelegramForbiddenError): + return False diff --git a/bot/filters/chat_type.py b/bot/filters/chat_type.py new file mode 100644 index 0000000..45bbef3 --- /dev/null +++ b/bot/filters/chat_type.py @@ -0,0 +1,105 @@ +""" +Фильтры для проверки типов чатов +""" +from typing import Union + +from aiogram.filters import BaseFilter +from aiogram.types import Message, CallbackQuery +from aiogram.enums import ChatType + +__all__ = ('IsPrivateChat', 'IsGroupChat', 'IsSuperGroupChat', 'IsChannelChat', 'IsAnyGroup') + + +class IsPrivateChat(BaseFilter): + """ + Проверяет, что сообщение из личного чата (приватный диалог с ботом). + + Example: + ```python + @router.message(Command("start"), IsPrivateChat()) + async def start_private(message: Message): + await message.answer("Привет в личке!") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + if isinstance(event, CallbackQuery): + event = event.message + + return event.chat.type == ChatType.PRIVATE + + +class IsGroupChat(BaseFilter): + """ + Проверяет, что сообщение из обычной группы (не супергруппы). + + Example: + ```python + @router.message(IsGroupChat()) + async def group_message(message: Message): + await message.answer("Это обычная группа") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + if isinstance(event, CallbackQuery): + event = event.message + + return event.chat.type == ChatType.GROUP + + +class IsSuperGroupChat(BaseFilter): + """ + Проверяет, что сообщение из супергруппы. + + Example: + ```python + @router.message(IsSuperGroupChat()) + async def supergroup_message(message: Message): + await message.answer("Это супергруппа") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + if isinstance(event, CallbackQuery): + event = event.message + + return event.chat.type == ChatType.SUPERGROUP + + +class IsChannelChat(BaseFilter): + """ + Проверяет, что сообщение из канала. + + Example: + ```python + @router.message(IsChannelChat()) + async def channel_message(message: Message): + await message.answer("Это канал") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + if isinstance(event, CallbackQuery): + event = event.message + + return event.chat.type == ChatType.CHANNEL + + +class IsAnyGroup(BaseFilter): + """ + Проверяет, что сообщение из любой группы (обычная или супергруппа). + + Example: + ```python + @router.message(Command("admin"), IsAnyGroup()) + async def admin_command(message: Message): + await message.answer("Команда доступна только в группах") + ``` + """ + + async def __call__(self, event: Union[Message, CallbackQuery]) -> bool: + if isinstance(event, CallbackQuery): + event = event.message + + return event.chat.type in (ChatType.GROUP, ChatType.SUPERGROUP) 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 diff --git a/bot/filters/msg_content.py b/bot/filters/msg_content.py new file mode 100644 index 0000000..548e8d5 --- /dev/null +++ b/bot/filters/msg_content.py @@ -0,0 +1,395 @@ +""" +Фильтры для проверки содержимого сообщений +""" +import re +from typing import Optional, Union + +from aiogram.filters import BaseFilter +from aiogram.types import Message, ContentType + +from middleware.loggers import logger + +__all__ = ( + 'IsReply', + 'IsForwarded', + 'HasMedia', + 'ContainsURL', + 'HasText', + 'HasCaption', + 'HasEntities', + 'MediaType' +) + + +class IsReply(BaseFilter): + """ + Проверяет, является ли сообщение ответом на другое сообщение. + + Example: + ```python + @router.message(IsReply()) + async def handle_reply(message: Message): + original = message.reply_to_message + await message.answer(f"Это ответ на: {original.text}") + ``` + """ + + async def __call__(self, message: Message) -> Union[bool, dict]: + is_reply = message.reply_to_message is not None + + if is_reply: + return { + 'is_reply': True, + 'reply_to_message': message.reply_to_message, + 'reply_to_user_id': message.reply_to_message.from_user.id if message.reply_to_message.from_user else None + } + + return False + + +class IsForwarded(BaseFilter): + """ + Проверяет, является ли сообщение пересланным. + + Поддерживает: + - Пересылку от пользователей (forward_from) + - Пересылку из каналов/групп (forward_from_chat) + - Скрытую пересылку (forward_sender_name) + + Example: + ```python + @router.message(IsForwarded()) + async def handle_forwarded(message: Message, forward_info: dict): + await message.answer(f"Переслано из: {forward_info['origin']}") + ``` + """ + + async def __call__(self, message: Message) -> Union[bool, dict]: + # Проверка различных типов пересылки + is_forwarded = ( + message.forward_origin is not None or # Новый API (aiogram 3.x) + message.forward_from is not None or + message.forward_from_chat is not None or + message.forward_sender_name is not None + ) + + if is_forwarded: + origin = "неизвестно" + + if message.forward_from: + origin = f"пользователь @{message.forward_from.username or message.forward_from.id}" + elif message.forward_from_chat: + origin = f"чат {message.forward_from_chat.title or message.forward_from_chat.id}" + elif message.forward_sender_name: + origin = f"скрытый пользователь ({message.forward_sender_name})" + + logger.debug( + f"Обнаружено пересланное сообщение из: {origin}", + log_type='FORWARD', + message=message + ) + + return { + 'is_forwarded': True, + 'origin': origin, + 'forward_date': message.forward_date + } + + return False + + +class HasMedia(BaseFilter): + """ + Проверяет, содержит ли сообщение медиа-контент. + + Attributes: + media_types: Список типов медиа для проверки (если None, проверяются все) + + Example: + ```python + # Любое медиа + @router.message(HasMedia()) + async def handle_media(message: Message): + await message.answer("Получено медиа!") + + # Только фото и видео + @router.message(HasMedia(['photo', 'video'])) + async def handle_visual(message: Message): + await message.answer("Фото или видео!") + ``` + """ + + def __init__(self, media_types: Optional[list[str]] = None): + """ + Args: + media_types: Список типов медиа ('photo', 'video', 'document', и т.д.) + Если None, проверяются все типы + """ + self.media_types = media_types + + async def __call__(self, message: Message) -> Union[bool, dict]: + # Все возможные типы медиа + media_checks = { + 'photo': message.photo, + 'video': message.video, + 'document': message.document, + 'audio': message.audio, + 'voice': message.voice, + 'video_note': message.video_note, + 'sticker': message.sticker, + 'animation': message.animation, + } + + # Если указаны конкретные типы, проверяем только их + if self.media_types: + has_media = any( + media_checks[media_type] + for media_type in self.media_types + if media_type in media_checks + ) + detected_type = next( + (media_type for media_type in self.media_types if media_checks.get(media_type)), + None + ) + else: + # Проверяем все типы + has_media = any(media_checks.values()) + detected_type = next( + (media_type for media_type, value in media_checks.items() if value), + None + ) + + if has_media: + return { + 'has_media': True, + 'media_type': detected_type, + 'content': media_checks[detected_type] + } + + return False + + +class ContainsURL(BaseFilter): + """ + Проверяет, содержит ли сообщение ссылки. + + Поддерживает: + - HTTP/HTTPS ссылки + - Telegram ссылки (t.me, tg://) + - Проверку через entities (более точная) + + Attributes: + strict: Использовать строгую проверку через entities + + Example: + ```python + @router.message(ContainsURL()) + async def handle_url(message: Message, url_info: dict): + urls = url_info['urls'] + await message.answer(f"Обнаружено {len(urls)} ссылок") + ``` + """ + + def __init__(self, strict: bool = False): + """ + Args: + strict: Если True, проверяет через entities (игнорирует текст в коде/pre) + """ + self.strict = strict + # Паттерн для поиска URL + self.url_pattern = re.compile( + r'https?://[^\s]+|' # http(s):// + r't\.me/[^\s]+|' # t.me/ + r'tg://[^\s]+', # tg:// + re.IGNORECASE + ) + + async def __call__(self, message: Message) -> Union[bool, dict]: + if not message.text and not message.caption: + return False + + text = message.text or message.caption + + if self.strict and message.entities: + # Строгая проверка через entities + url_entities = [ + entity for entity in message.entities + if entity.type in ('url', 'text_link') + ] + + if url_entities: + urls = [] + for entity in url_entities: + if entity.type == 'url': + url = text[entity.offset:entity.offset + entity.length] + urls.append(url) + elif entity.type == 'text_link': + urls.append(entity.url) + + return { + 'contains_url': True, + 'urls': urls, + 'url_count': len(urls) + } + else: + # Простая проверка через regex + urls = self.url_pattern.findall(text) + + if urls: + return { + 'contains_url': True, + 'urls': urls, + 'url_count': len(urls) + } + + return False + + +class HasText(BaseFilter): + """ + Проверяет, содержит ли сообщение текст. + + Attributes: + min_length: Минимальная длина текста (по умолчанию 1) + max_length: Максимальная длина текста (по умолчанию None) + + Example: + ```python + # Любой текст + @router.message(HasText()) + async def handle_text(message: Message): + await message.answer("Получен текст!") + + # Текст от 10 до 100 символов + @router.message(HasText(min_length=10, max_length=100)) + async def handle_medium_text(message: Message): + await message.answer("Текст подходящей длины!") + ``` + """ + + def __init__(self, min_length: int = 1, max_length: Optional[int] = None): + self.min_length = min_length + self.max_length = max_length + + async def __call__(self, message: Message) -> Union[bool, dict]: + if not message.text: + return False + + text_length = len(message.text) + + # Проверка длины + if text_length < self.min_length: + return False + + if self.max_length and text_length > self.max_length: + return False + + return { + 'has_text': True, + 'text_length': text_length, + 'text': message.text + } + + +class HasCaption(BaseFilter): + """ + Проверяет, есть ли у медиа подпись. + + Example: + ```python + @router.message(HasCaption()) + async def handle_caption(message: Message): + await message.answer(f"Подпись: {message.caption}") + ``` + """ + + async def __call__(self, message: Message) -> Union[bool, dict]: + if message.caption: + return { + 'has_caption': True, + 'caption': message.caption, + 'caption_length': len(message.caption) + } + return False + + +class HasEntities(BaseFilter): + """ + Проверяет наличие entities (упоминания, хештеги, команды и т.д.). + + Attributes: + entity_types: Список типов entities для проверки + + Example: + ```python + # Любые entities + @router.message(HasEntities()) + async def handle_entities(message: Message): + pass + + # Только упоминания и хештеги + @router.message(HasEntities(['mention', 'hashtag'])) + async def handle_mentions(message: Message): + pass + ``` + """ + + def __init__(self, entity_types: Optional[list[str]] = None): + """ + Args: + entity_types: Список типов ('mention', 'hashtag', 'bot_command', и т.д.) + """ + self.entity_types = entity_types + + async def __call__(self, message: Message) -> Union[bool, dict]: + if not message.entities: + return False + + if self.entity_types: + # Фильтруем по типам + matching_entities = [ + entity for entity in message.entities + if entity.type in self.entity_types + ] + + if matching_entities: + return { + 'has_entities': True, + 'entities': matching_entities, + 'entity_count': len(matching_entities) + } + else: + # Любые entities + return { + 'has_entities': True, + 'entities': message.entities, + 'entity_count': len(message.entities) + } + + return False + + +class MediaType(BaseFilter): + """ + Проверяет точный тип контента сообщения. + + Attributes: + content_type: Тип контента из ContentType enum + + Example: + ```python + @router.message(MediaType(ContentType.PHOTO)) + async def handle_photo(message: Message): + await message.answer("Это фото!") + ``` + """ + + def __init__(self, content_type: Union[ContentType, str]): + """ + Args: + content_type: Тип контента (ContentType enum или строка) + """ + self.content_type = content_type if isinstance(content_type, str) else content_type.value + + async def __call__(self, message: Message) -> bool: + return message.content_type == self.content_type diff --git a/bot/filters/spam.py b/bot/filters/spam.py new file mode 100644 index 0000000..9722ab8 --- /dev/null +++ b/bot/filters/spam.py @@ -0,0 +1,111 @@ +""" +Фильтры для проверки сообщений на спам и банворды +""" +from typing import Optional, Callable + +from aiogram.filters import BaseFilter +from aiogram.types import Message + +from middleware.loggers import logger + +__all__ = ('HasSpam', 'IsWhitelisted') + + +class HasSpam(BaseFilter): + """ + Проверяет, содержит ли сообщение запрещенные слова (спам). + + Attributes: + check_spam_func: Функция проверки спама (передается при инициализации) + + Example: + ```python + from utils.spam_checker import check_spam + + @router.message(HasSpam(check_spam)) + async def spam_detected(message: Message): + await message.delete() + await message.answer("⚠️ Сообщение содержит запрещенные слова") + ``` + """ + + def __init__(self, check_spam_func: Callable[[str], bool]): + """ + Args: + check_spam_func: Функция для проверки спама + """ + self.check_spam = check_spam_func + + async def __call__(self, message: Message) -> Optional[dict]: + """ + Проверка сообщения на спам. + + Returns: + dict или None: Информация о найденном спаме или None + """ + if not message.text: + return None + + text_lower = message.text.lower() + has_spam = self.check_spam(text_lower) + + if has_spam: + logger.warning( + f"Обнаружен спам в сообщении", + log_type='SPAM', + message=message + ) + return {'has_spam': True, 'text': text_lower} + + return None + + +class IsWhitelisted(BaseFilter): + """ + Проверяет, содержит ли сообщение слова из белого списка (исключения). + + Используется для защиты от ложных срабатываний спам-фильтра. + + Attributes: + check_whitelist_func: Функция проверки белого списка + + Example: + ```python + from utils.spam_checker import check_whitelist + + @router.message(IsWhitelisted(check_whitelist)) + async def whitelisted_message(message: Message): + # Сообщение содержит исключение, пропускаем проверку спама + pass + ``` + """ + + def __init__(self, check_whitelist_func: Callable[[str], bool]): + """ + Args: + check_whitelist_func: Функция для проверки белого списка + """ + self.check_whitelist = check_whitelist_func + + async def __call__(self, message: Message) -> Optional[bool]: + """ + Проверка на наличие в белом списке. + + Returns: + bool или None: True если в белом списке, None если нет + """ + if not message.text: + return None + + text_lower = message.text.lower() + is_whitelisted = self.check_whitelist(text_lower) + + if is_whitelisted: + logger.debug( + f"Сообщение содержит исключение из белого списка", + log_type='WHITELIST', + message=message + ) + return True + + return None diff --git a/bot/filters/subscription.py b/bot/filters/subscription.py new file mode 100644 index 0000000..3158efe --- /dev/null +++ b/bot/filters/subscription.py @@ -0,0 +1,246 @@ +""" +Фильтр проверки подписки пользователя на каналы/группы +""" +from typing import Union, Optional +from dataclasses import dataclass + +from aiogram import Bot +from aiogram.enums import ChatMemberStatus +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError +from aiogram.filters import BaseFilter +from aiogram.types import Message, CallbackQuery + +from middleware.loggers import logger + +__all__ = ('IsSubscribed', 'SubscriptionChecker') + + +@dataclass +class ChannelInfo: + """Информация о канале для проверки подписки""" + id: Union[str, int] + name: Optional[str] = None + invite_link: Optional[str] = None + + +class SubscriptionChecker: + """ + Вспомогательный класс для проверки подписок. + Может использоваться отдельно от фильтра. + """ + + # Статусы, считающиеся подпиской + SUBSCRIBED_STATUSES: set[str] = { + ChatMemberStatus.MEMBER, + ChatMemberStatus.ADMINISTRATOR, + ChatMemberStatus.CREATOR + } + + # Статусы, означающие отсутствие подписки + NOT_SUBSCRIBED_STATUSES: set[str] = { + ChatMemberStatus.LEFT, + ChatMemberStatus.KICKED, + ChatMemberStatus.RESTRICTED # Опционально + } + + @classmethod + async def is_subscribed( + cls, + bot: Bot, + user_id: int, + channel_id: Union[str, int] + ) -> bool: + """ + Проверяет подписку одного пользователя на один канал. + + Args: + bot: Экземпляр бота + user_id: ID пользователя + channel_id: ID или username канала + + Returns: + bool: True если подписан + """ + try: + member = await bot.get_chat_member( + chat_id=channel_id, + user_id=user_id + ) + + is_sub = member.status in cls.SUBSCRIBED_STATUSES + + logger.debug( + f"Проверка подписки user={user_id} на канал={channel_id}: {member.status} ({'✅' if is_sub else '❌'})", + log_type='SUBSCRIPTION' + ) + + return is_sub + + except TelegramBadRequest as e: + logger.warning( + f"Канал {channel_id} недоступен или неверный ID: {e}", + log_type='SUBSCRIPTION' + ) + return False + + except TelegramForbiddenError as e: + logger.error( + f"Бот не имеет доступа к каналу {channel_id}: {e}", + log_type='SUBSCRIPTION' + ) + return False + + except Exception as e: + logger.error( + f"Непредвиденная ошибка проверки подписки на {channel_id}: {e}", + log_type='SUBSCRIPTION' + ) + return False + + @classmethod + async def check_all_channels( + cls, + bot: Bot, + user_id: int, + channels: list[Union[str, int]] + ) -> dict[Union[str, int], bool]: + """ + Проверяет подписку на несколько каналов одновременно. + + Args: + bot: Экземпляр бота + user_id: ID пользователя + channels: Список ID/username каналов + + Returns: + dict: Словарь {channel_id: is_subscribed} + """ + results = {} + + for channel in channels: + results[channel] = await cls.is_subscribed(bot, user_id, channel) + + return results + + @classmethod + async def get_not_subscribed_channels( + cls, + bot: Bot, + user_id: int, + channels: list[Union[str, int]] + ) -> list[Union[str, int]]: + """ + Возвращает список каналов, на которые пользователь НЕ подписан. + + Args: + bot: Экземпляр бота + user_id: ID пользователя + channels: Список ID/username каналов + + Returns: + list: Список каналов без подписки + """ + not_subscribed = [] + + for channel in channels: + if not await cls.is_subscribed(bot, user_id, channel): + not_subscribed.append(channel) + + return not_subscribed + + +class IsSubscribed(BaseFilter): + """ + Фильтр для проверки подписки пользователя на каналы/группы. + + Поддерживает: + - Публичные каналы (username: "@channel_name") + - Приватные каналы/группы (ID: -1001234567890) + - Проверку всех или хотя бы одного канала + - Работу с Message и CallbackQuery + + Attributes: + channels: Список ID или username каналов для проверки + require_all: Требовать подписку на все каналы (True) или хотя бы один (False) + + Examples: + >> # Проверка подписки на один канал + >> @router.message(IsSubscribed(["@my_channel"])) + >> async def handler(message: Message): + ... await message.answer("Ты подписан!") + + >> # Проверка на несколько каналов (все обязательны) + >> @router.message(IsSubscribed(["@channel1", -1001234567890], require_all=True)) + >> async def handler(message: Message): + ... await message.answer("Ты подписан на все каналы!") + + >> # Проверка на несколько каналов (хотя бы один) + >> @router.message(IsSubscribed(["@channel1", "@channel2"], require_all=False)) + >> async def handler(message: Message): + ... await message.answer("Ты подписан хотя бы на один канал!") + """ + + def __init__( + self, + channels: list[Union[str, int]], + require_all: bool = True + ) -> None: + """ + Инициализация фильтра. + + Args: + channels: Список ID или username каналов + require_all: True = все каналы, False = хотя бы один + """ + if not channels: + raise ValueError("Список каналов не может быть пустым") + + self.channels = channels + self.require_all = require_all + + async def __call__( + self, + event: Union[Message, CallbackQuery], + bot: Bot + ) -> Union[bool, dict]: + """ + Проверка подписки. + + Args: + event: Message или CallbackQuery + bot: Экземпляр бота + + Returns: + bool или dict: True/False для простой проверки, + dict с деталями для сложной логики + """ + user_id = event.from_user.id + + # Проверка всех каналов + results = await SubscriptionChecker.check_all_channels( + bot, user_id, self.channels + ) + + # Логика проверки + if self.require_all: + # Все каналы обязательны + is_passed = all(results.values()) + else: + # Хотя бы один канал + is_passed = any(results.values()) + + # Логирование + if not is_passed: + not_subscribed = [ch for ch, sub in results.items() if not sub] + logger.info( + f"Пользователь {user_id} не подписан на: {not_subscribed}", + log_type='SUBSCRIPTION', + message=event if isinstance(event, Message) else None + ) + + # Возвращаем результат + детали для handler + return { + 'is_subscribed': is_passed, + 'subscription_results': results, + 'not_subscribed_channels': [ch for ch, sub in results.items() if not sub] + } if not is_passed else is_passed diff --git a/bot/handlers/__init__.py b/bot/handlers/__init__.py new file mode 100644 index 0000000..ea860be --- /dev/null +++ b/bot/handlers/__init__.py @@ -0,0 +1,14 @@ +from aiogram import Router + +from .commands import router as cmd_routers +from .messages import router as messages_routers + +# Настройка экспорта и роутера +__all__ = ("router",) +router: Router = Router(name=__name__) + +# Подключение роутеров +router.include_routers( + cmd_routers, + messages_routers, +) diff --git a/bot/handlers/commands/__init__.py b/bot/handlers/commands/__init__.py new file mode 100644 index 0000000..f8baa9f --- /dev/null +++ b/bot/handlers/commands/__init__.py @@ -0,0 +1,16 @@ +from aiogram import Router + +#from .admins import router as admin_cmd_router +from .users import router as users_cmd_router +#from .settings import router as settings_cmd_router + +# Настройка экспорта и роутера +__all__ = ("router",) +router: Router = Router(name=__name__) + +# Подключение роутеров +router.include_routers( + #settings_cmd_router, + #admin_cmd_router, + users_cmd_router, +) diff --git a/bot/handlers/commands/admins/__init__.py b/bot/handlers/commands/admins/__init__.py new file mode 100644 index 0000000..fec40b1 --- /dev/null +++ b/bot/handlers/commands/admins/__init__.py @@ -0,0 +1,18 @@ +from aiogram import Router + +#from .ban_cmd import router as ban_cmd_router +from .all_cmd import router as all_cmd_router +from .pin_cmd import router as pin_cmd_router +from .kick_cmd import router as kick_cmd_router + +# Настройка экспорта и роутера +__all__ = ("router",) +router: Router = Router(name=__name__) + +router.include_routers( +#ban_cmd_router, + kick_cmd_router, + pin_cmd_router, + all_cmd_router, + +) diff --git a/bot/handlers/commands/admins/all_cmd.py b/bot/handlers/commands/admins/all_cmd.py new file mode 100644 index 0000000..b7807a0 --- /dev/null +++ b/bot/handlers/commands/admins/all_cmd.py @@ -0,0 +1,81 @@ +from asyncio import create_task + +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message +from aiogram.exceptions import TelegramBadRequest +from aiogram.fsm.context import FSMContext + +from bot.core.bots import bot, BotInfo +from bot.filters import IsOwner +from bot.utils import status_clear, auto_delete_message, hidden_admins_message +from configs import COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) + +# Ключ для команды +CMD: str = "all" +# Инициализация роутера +router: Router = Router(name=f"{CMD}_cmd_router") + + +@router.message( + F.text.lower().regexp(rf"^({'|'.join(COMMANDS[CMD])})\s?.*"), # ловим текст без префикса + F.chat.type.in_({"supergroup", "group"}), + IsOwner() +) +@router.message( + Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), + F.chat.type.in_({"supergroup", "group"}), + IsOwner() +) +async def notify_all_text(message: Message, state: FSMContext) -> None: + """ + Обработчик команды /all, /call и текстовых эквивалентов типа "Калл Привет всем". + + Функционал: + 1. Считывает весь текст после команды. + 2. Формирует скрытое сообщение для администраторов. + 3. Отправляет сообщение в чат. + 4. Автоматически удаляет сообщение через неделю. + 5. Пытается закрепить сообщение в чате. + + Args: + message (Message): Объект входящего сообщения. + state (FSMContext): Контекст FSM, используется для очистки состояния. + """ + # Очистка состояния FSM перед выполнением команды + await status_clear(update=message, state=state) + + # Извлечение текста после команды + parts: list[str] = message.text.split(" ", 1) + custom_text: str = parts[1] if len(parts) > 1 else "⚡ Внимание всем!" + + # Формирование скрытого текста для администраторов + hidden_text: str = await hidden_admins_message(message=message, text=custom_text) + + # Отправка сообщения в чат + sent_message: Message = await message.answer(hidden_text) + + # Запуск асинхронной задачи по удалению сообщения через 7 дней + create_task( + auto_delete_message( + chat_id=message.chat.id, + message_id=sent_message.message_id, + delay=604800 # 7 дней в секундах + ) + ) + + # Попытка закрепить сообщение и удалить "системное" сообщение о закреплении + try: + await bot.pin_chat_message( + chat_id=message.chat.id, + message_id=sent_message.message_id, + disable_notification=False + ) + # Иногда Telegram создает дополнительное уведомление при закреплении + await bot.delete_message(chat_id=message.chat.id, message_id=sent_message.message_id + 1) + logger.debug(f"[ALL] Сообщение закреплено: {custom_text}") + except TelegramBadRequest as e: + logger.error(f"[ALL] Ошибка закрепления сообщения: {e}") diff --git a/bot/handlers/commands/admins/ban_cmd.py b/bot/handlers/commands/admins/ban_cmd.py new file mode 100644 index 0000000..9e5f369 --- /dev/null +++ b/bot/handlers/commands/admins/ban_cmd.py @@ -0,0 +1,258 @@ +from aiogram import Router +from aiogram.filters import Command +from aiogram.fsm.context import FSMContext +from aiogram.types import Message, User +from html import escape + +from bot.filters import IsAdmin +from bot.utils import status_clear +from configs import COMMANDS +from database import db + +# Настройки роутера +__all__ = ("router",) + +from middleware import logger + +CMD: str = "ban" +router: Router = Router(name=f"{CMD}_cmd_router") + + +@router.message(Command(*COMMANDS[CMD], ignore_case=True), IsAdmin()) +async def ban_user_cmd(message: Message, state: FSMContext) -> None: + """ + Команда /ban для блокировки пользователей. + Использование: /ban или ответ на сообщение пользователя + /ban + """ + await status_clear(update=message, state=state) + + try: + # Проверяем есть ли ответ на сообщение + if message.reply_to_message: + # Бан по ответу на сообщение + target_user: User | None = message.reply_to_message.from_user + if not target_user: + await message.answer("❌ Не удалось определить пользователя") + return + + target_user_id: int = target_user.id + target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}" + + # Проверяем, не пытаемся ли забанить бота + if target_user_id == message.bot.id: + await message.answer("❌ Нельзя заблокировать бота!") + return + + # Баним пользователя + success: bool = await _ban_user(target_user_id, target_username, message) + + if success: + safe_username: str = escape(target_username) + response_text = f"✅ Пользователь {safe_username} (ID: {target_user_id}) заблокирован!" + + # Пытаемся забанить в чате (если команда вызвана в группе/чате) + if message.chat.type in ["group", "supergroup"]: + try: + await message.bot.ban_chat_member( + chat_id=message.chat.id, + user_id=target_user_id + ) + response_text += "\n🚫 Пользователь исключен из чата." + except Exception as e: + logger.warning(f"Не удалось исключить пользователя из чата: {e}") + response_text += "\n⚠️ Не удалось исключить пользователя из чата." + + await message.answer( + text=response_text, + parse_mode=None # Отключаем разметку + ) + else: + await message.answer("❌ Не удалось заблокировать пользователя") + + else: + # Бан по ID пользователя + command_parts: list[str] = message.text.split() + if len(command_parts) < 2: + await message.answer( + "ℹ️ Использование команды:\n" + "• Ответьте на сообщение пользователя командой /ban\n" + "• Или укажите ID: /ban " + ) + return + + try: + target_user_id: int = int(command_parts[1]) + + # Проверяем, не пытаемся ли забанить бота + if target_user_id == message.bot.id: + await message.answer("❌ Нельзя заблокировать бота!") + return + + success: bool = await _ban_user(target_user_id, f"ID{target_user_id}", message) + + if success: + response_text = f"✅ Пользователь (ID: {target_user_id}) заблокирован!" + + # Пытаемся забанить в чате + if message.chat.type in ["group", "supergroup"]: + try: + await message.bot.ban_chat_member( + chat_id=message.chat.id, + user_id=target_user_id + ) + response_text += "\n🚫 Пользователь исключен из чата." + except Exception as e: + logger.warning(f"Не удалось исключить пользователя из чата: {e}") + response_text += "\n⚠️ Не удалось исключить пользователя из чата." + + await message.answer( + text=response_text, + parse_mode=None + ) + else: + await message.answer("❌ Пользователь не найден или уже заблокирован") + + except ValueError: + await message.answer("❌ Неверный формат ID пользователя") + + except Exception as e: + logger.error(f"Ошибка в команде /ban: {e}") + await message.answer( + "⚠️ Произошла непредвиденная ошибка при выполнении команды.\n" + "Попробуйте повторить действие позже или нажмите /start" + ) + + +async def _ban_user(user_id: int, username: str, message: Message) -> bool: + """ + Внутренняя функция для блокировки пользователя. + """ + try: + # Сначала проверяем существует ли пользователь + user: User | None = await db.get_user(user_id) + + if not user: + # Если пользователя нет - создаем его забаненным + await db.add_user( + user_id=user_id, + username=username, + full_name=username + ) + + # Баним пользователя + await db.ban_user(user_id) + + # Логируем действие + admin_username = message.from_user.username or message.from_user.full_name or f"ID{message.from_user.id}" + logger.info(f"🛑 Админ @{admin_username} заблокировал пользователя @{username} (ID: {user_id})") + + return True + + except Exception as e: + logger.error(f"❌ Ошибка при блокировке пользователя {user_id}: {e}") + return False + + +@router.message(Command("unban", ignore_case=True), IsAdmin()) +async def unban_user_cmd(message: Message, state: FSMContext) -> None: + """ + Команда /unban для разблокировки пользователей. + """ + await status_clear(update=message, state=state) + + try: + if message.reply_to_message: + target_user: User | None = message.reply_to_message.from_user + if not target_user: + await message.answer("❌ Не удалось определить пользователя") + return + + target_user_id: int = target_user.id + target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}" + else: + command_parts: list[str] = message.text.split() + if len(command_parts) < 2: + await message.answer( + "ℹ️ Использование команды:\n" + "• Ответьте на сообщение пользователя командой /unban\n" + "• Или укажите ID: /unban " + ) + return + + try: + target_user_id: int = int(command_parts[1]) + target_username: str = f"ID{target_user_id}" + except ValueError: + await message.answer("❌ Неверный формат ID пользователя") + return + + # Разбаниваем пользователя + await db.unban_user(target_user_id) + + # Логируем действие + admin_username: str = message.from_user.username or message.from_user.full_name or f"ID{message.from_user.id}" + logger.info(f"🔓 Админ @{admin_username} разблокировал пользователя @{target_username} (ID: {target_user_id})") + + # Экранируем специальные символы + safe_username: str = escape(target_username) + + response_text = f"✅ Пользователь {safe_username} (ID: {target_user_id}) разблокирован!" + + # Пытаемся разбанить в чате + if message.chat.type in ["group", "supergroup"]: + try: + await message.bot.unban_chat_member( + chat_id=message.chat.id, + user_id=target_user_id + ) + response_text += "\n👥 Пользователь может вернуться в чат." + except Exception as e: + logger.warning(f"Не удалось разблокировать пользователя в чате: {e}") + + await message.answer( + text=response_text, + parse_mode=None + ) + + except Exception as e: + logger.error(f"❌ Ошибка при разблокировке пользователя: {e}") + await message.answer("❌ Не удалось разблокировать пользователя") + + +@router.message(Command("banned_list", ignore_case=True), IsAdmin()) +async def banned_list_cmd(message: Message, state: FSMContext) -> None: + """ + Команда /banned_list для просмотра списка забаненных пользователей. + """ + await status_clear(update=message, state=state) + + try: + # Получаем всех пользователей включая забаненных + all_users: list[User] = await db.get_all_users(include_banned=True) + + # Фильтруем только забаненных + banned_users: list[User] = [user for user in all_users if getattr(user, 'status', None) == "banned"] + + if not banned_users: + await message.answer("📭 Список забаненных пользователей пуст") + return + + # Формируем сообщение со списком + banned_list: str = "🚫 Заблокированные пользователи:\n\n" + + for user in banned_users[:50]: # Ограничиваем вывод + username: str = f"@{user.username}" if getattr(user, 'username', None) else getattr(user, 'full_name', + 'Неизвестно') + # Экранируем специальные символы + safe_username = escape(username) + user_id = getattr(user, 'id', 'N/A') + banned_list += f"• {safe_username} (ID: {user_id})\n" + + if len(banned_users) > 50: + banned_list += f"\n... и еще {len(banned_users) - 50} пользователей" + + await message.answer(banned_list, parse_mode=None) + + except Exception as e: + logger.error(f"❌ Ошибка при получении списка забаненных: {e}") + await message.answer("❌ Не удалось получить список забаненных пользователей") diff --git a/bot/handlers/commands/admins/kick_cmd.py b/bot/handlers/commands/admins/kick_cmd.py new file mode 100644 index 0000000..e0fcadb --- /dev/null +++ b/bot/handlers/commands/admins/kick_cmd.py @@ -0,0 +1,277 @@ +from aiogram import Router +from aiogram.filters import Command +from aiogram.fsm.context import FSMContext +from aiogram.types import Message, User +from html import escape + +from bot import bot +from bot.filters import IsAdmin +from bot.utils import status_clear +from configs import COMMANDS + +# Настройки роутера +__all__ = ("router",) + +from middleware import logger + +CMD: str = "kick" +router: Router = Router(name=f"{CMD}_cmd_router") + + +@router.message(Command(*COMMANDS[CMD], ignore_case=True), IsAdmin()) +async def kick_user_cmd(message: Message, state: FSMContext) -> None: + """ + Команда /kick для кика пользователей из чата. + Использование: /kick или ответ на сообщение пользователя + /kick + """ + await status_clear(update=message, state=state) + + # Проверяем, что команда используется в группе/супергруппе + if message.chat.type not in ["group", "supergroup"]: + await message.answer("❌ Эта команда работает только в группах и супергруппах!") + return + + # Проверяем есть ли ответ на сообщение + if message.reply_to_message: + # Кик по ответу на сообщение + target_user: User | None = message.reply_to_message.from_user + target_user_id: int = target_user.id + target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}" + + # Кикаем пользователя + success: bool = await _kick_user(target_user_id, target_username, message) + + if success: + safe_username: str = escape(target_username) + await message.answer( + text=f"👢 Пользователь {safe_username} (ID: {target_user_id}) кикнут из чата!", + ) + else: + await message.answer("❌ Не удалось кикнуть пользователя") + + else: + # Кик по ID пользователя + command_parts: list[str] = message.text.split() + if len(command_parts) < 2: + await message.answer( + "ℹ️ Использование команды:\n" + "• Ответьте на сообщение пользователя командой /kick\n" + "• Или укажите ID: /kick " + ) + return + + try: + target_user_id: int = int(command_parts[1]) + success: bool = await _kick_user(target_user_id, f"ID{target_user_id}", message) + + if success: + await message.answer( + text=f"👢 Пользователь (ID: {target_user_id}) кикнут из чата!", + parse_mode=None # Отключаем разметку + ) + else: + await message.answer("❌ Пользователь не найден или не удалось кикнуть") + + except ValueError: + await message.answer("❌ Неверный формат ID пользователя") + + +async def _kick_user(user_id: int, username: str, message: Message) -> bool: + """ + Внутренняя функция для кика пользователя из чата. + + Args: + user_id: ID пользователя для кика + username: Имя пользователя для логов + message: Объект сообщения для контекста + + Returns: + bool: Успешно ли кикнут пользователь + """ + try: + # Проверяем, что бот имеет права администратора в чате + bot_member = await bot.get_chat_member(message.chat.id, bot.id) + if not bot_member.can_restrict_members: + await message.answer("❌ У меня нет прав для кика пользователей!") + return False + + # Проверяем, что целевой пользователь не является администратором/владельцем + target_member = await bot.get_chat_member(message.chat.id, user_id) + if target_member.status in ["creator", "administrator"]: + await message.answer("❌ Нельзя кикнуть администратора или создателя чата!") + return False + + # Проверяем, что отправитель команды имеет права администратора + admin_member = await bot.get_chat_member(message.chat.id, message.from_user.id) + if admin_member.status not in ["creator", "administrator"]: + await message.answer("❌ У вас нет прав для кика пользователей!") + return False + + # Кикаем пользователя из чата + await bot.ban_chat_member( + chat_id=message.chat.id, + user_id=user_id, + revoke_messages=False # Не удаляем сообщения пользователя + ) + + # Сразу разбаниваем, чтобы пользователь мог вернуться по приглашению + await bot.unban_chat_member( + chat_id=message.chat.id, + user_id=user_id + ) + + # Логируем действие + admin_username = message.from_user.username or message.from_user.full_name + logger.info( + f"👢 Админ @{admin_username} кикнул пользователя @{username} (ID: {user_id}) из чата {message.chat.title}") + + return True + + except Exception as e: + logger.error(f"❌ Ошибка при кике пользователя {user_id}: {e}") + await message.answer(f"❌ Ошибка при кике пользователя: {str(e)}") + return False + + +@router.message(Command("kick_ban", ignore_case=True), IsAdmin()) +async def kick_ban_user_cmd(message: Message, state: FSMContext) -> None: + """ + Команда /kick_ban для кика пользователя с удалением сообщений. + Использование: /kick_ban или ответ на сообщение пользователя + /kick_ban + """ + await status_clear(update=message, state=state) + + # Проверяем, что команда используется в группе/супергруппе + if message.chat.type not in ["group", "supergroup"]: + await message.answer("❌ Эта команда работает только в группах и супергруппах!") + return + + # Проверяем есть ли ответ на сообщение + if message.reply_to_message: + # Кик по ответу на сообщение + target_user: User | None = message.reply_to_message.from_user + target_user_id: int = target_user.id + target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}" + + # Кикаем пользователя с удалением сообщений + success: bool = await _kick_ban_user(target_user_id, target_username, message) + + if success: + safe_username: str = escape(target_username) + await message.answer( + text=f"💥 Пользователь {safe_username} (ID: {target_user_id}) кикнут с удалением сообщений!", + parse_mode=None # Отключаем разметку + ) + else: + await message.answer("❌ Не удалось кикнуть пользователя") + + else: + # Кик по ID пользователя + command_parts: list[str] = message.text.split() + if len(command_parts) < 2: + await message.answer( + "ℹ️ Использование команды:\n" + "• Ответьте на сообщение пользователя командой /kick_ban\n" + "• Или укажите ID: /kick_ban " + ) + return + + try: + target_user_id: int = int(command_parts[1]) + success: bool = await _kick_ban_user(target_user_id, f"ID{target_user_id}", message) + + if success: + await message.answer( + text=f"💥 Пользователь (ID: {target_user_id}) кикнут с удалением сообщений!", + parse_mode=None # Отключаем разметку + ) + else: + await message.answer("❌ Пользователь не найден или не удалось кикнуть") + + except ValueError: + await message.answer("❌ Неверный формат ID пользователя") + + +async def _kick_ban_user(user_id: int, username: str, message: Message) -> bool: + """ + Внутренняя функция для кика пользователя с удалением сообщений. + + Args: + user_id: ID пользователя для кика + username: Имя пользователя для логов + message: Объект сообщения для контекста + + Returns: + bool: Успешно ли кикнут пользователь + """ + try: + # Проверяем, что бот имеет права администратора в чате + bot_member = await bot.get_chat_member(message.chat.id, bot.id) + if not bot_member.can_restrict_members: + await message.answer("❌ У меня нет прав для кика пользователей!") + return False + + # Проверяем, что целевой пользователь не является администратором/владельцем + target_member = await bot.get_chat_member(message.chat.id, user_id) + if target_member.status in ["creator", "administrator"]: + await message.answer("❌ Нельзя кикнуть администратора или создателя чата!") + return False + + # Проверяем, что отправитель команды имеет права администратора + admin_member = await bot.get_chat_member(message.chat.id, message.from_user.id) + if admin_member.status not in ["creator", "administrator"]: + await message.answer("❌ У вас нет прав для кика пользователей!") + return False + + # Кикаем пользователя из чата с удалением сообщений + await bot.ban_chat_member( + chat_id=message.chat.id, + user_id=user_id, + revoke_messages=True # Удаляем сообщения пользователя + ) + + # Сразу разбаниваем, чтобы пользователь мог вернуться по приглашению + await bot.unban_chat_member( + chat_id=message.chat.id, + user_id=user_id + ) + + # Логируем действие + admin_username = message.from_user.username or message.from_user.full_name + logger.info( + f"💥 Админ @{admin_username} кикнул пользователя @{username} (ID: {user_id}) из чата {message.chat.title} с удалением сообщений") + + return True + + except Exception as e: + logger.error(f"❌ Ошибка при кике пользователя {user_id} с удалением сообщений: {e}") + await message.answer(f"❌ Ошибка при кике пользователя: {str(e)}") + return False + + +@router.message(Command("kick_list", ignore_case=True), IsAdmin()) +async def kick_help_cmd(message: Message, state: FSMContext) -> None: + """ + Команда /kick_list для показа справки по командам кика. + """ + await status_clear(update=message, state=state) + + help_text = """ +🤖 **Команды модерации:** + +**👢 /kick** - Кикнуть пользователя (может вернуться по приглашению) +• Ответьте на сообщение пользователя с командой /kick +• Или используйте: /kick + +**💥 /kick_ban** - Кикнуть пользователя с удалением сообщений +• Ответьте на сообщение пользователя с командой /kick_ban +• Или используйте: /kick_ban + +**🚫 /ban** - Полностью забанить пользователя +**🔓 /unban** - Разбанить пользователя +**📋 /banned_list** - Список забаненных + +⚠️ *Команды работают только в группах и требуют прав администратора* + """ + + await message.answer(help_text, parse_mode=None) diff --git a/bot/handlers/commands/admins/pin_cmd.py b/bot/handlers/commands/admins/pin_cmd.py new file mode 100644 index 0000000..63e29d4 --- /dev/null +++ b/bot/handlers/commands/admins/pin_cmd.py @@ -0,0 +1,77 @@ +from asyncio import create_task +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.fsm.context import FSMContext +from aiogram.types import Message, CallbackQuery +from bot.core.bots import BotInfo, bot +from bot.filters import IsOwner +from bot.templates import msg +from bot.utils import status_clear +from bot.utils.auto_delete import auto_delete_message +from configs import COMMANDS + +__all__ = ("router",) +CMD: str = "pin".lower() +router: Router = Router(name=f"{CMD}_cmd_router") + + +@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner()) +async def pin_cmd(message: Message, state: FSMContext) -> None: + """ + Обработчик команды /pin для закрепления последнего сообщения или ответа. + """ + # Если есть reply → закрепляем его, иначе закрепляем предыдущее сообщение + if message.reply_to_message: + target_message_id = message.reply_to_message.message_id + else: + # Закрепляем предыдущее сообщение (команда - 1) + target_message_id = message.message_id - 1 + + try: + await bot.pin_chat_message( + chat_id=message.chat.id, + message_id=target_message_id, + disable_notification=False + ) + + # Автоудаление через 7 суток (удаляем закрепленное сообщение) + create_task( + auto_delete_message( + chat_id=message.chat.id, + message_id=target_message_id, + delay=604800 + ) + ) + + await msg(update=message, text="✅ Сообщение успешно закреплено", state=state) + + except Exception as e: + await msg(update=message, text=f"❌ Ошибка закрепления: {e}", state=state) + + +@router.callback_query(F.data.casefold().isin(COMMANDS[CMD]), IsOwner()) +async def pin_callback(callback: CallbackQuery, state: FSMContext) -> None: + """ + Обработчик кнопки с callback_data="pin". + """ + await status_clear(update=callback.message, state=state) + + try: + await bot.pin_chat_message( + chat_id=callback.message.chat.id, + message_id=callback.message.message_id, + disable_notification=False + ) + + create_task( + auto_delete_message( + chat_id=callback.message.chat.id, + message_id=callback.message.message_id, + delay=604800 + ) + ) + + await callback.answer("✅ Сообщение закреплено") + + except Exception as e: + await callback.answer(f"❌ Ошибка: {e}", show_alert=True) diff --git a/bot/handlers/commands/admins/settings_cmd.py b/bot/handlers/commands/admins/settings_cmd.py new file mode 100644 index 0000000..7131f13 --- /dev/null +++ b/bot/handlers/commands/admins/settings_cmd.py @@ -0,0 +1,51 @@ +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.fsm.context import FSMContext +from aiogram.types import Message, CallbackQuery, InlineKeyboardButton +from aiogram.utils.keyboard import InlineKeyboardBuilder +from aiogram.utils.i18n import gettext as _ + +from bot.templates import msg_photo +from bot.utils.interesting_facts import interesting_fact +from bot.core.bots import BotInfo +from configs import COMMANDS, RpValue + +# Настройки экспорта и роутера +__all__ = ("router",) +CMD: str = "settings".lower() +router: Router = Router(name=f"{CMD}_cmd_router") + + +@router.callback_query(F.data.lower() == CMD) +@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True)) +async def start_cmd(message: Message | CallbackQuery, state: FSMContext) -> None: + """Обработчик команды /start""" + await state.clear() + + # Создание инлайн-клавиатуры + ikb: InlineKeyboardBuilder = InlineKeyboardBuilder() + ikb.row(InlineKeyboardButton(text="Инфо-канал🗂", url=CustomConfig.INFO_URL)) + ikb.row(InlineKeyboardButton(text="Вступление🚀", callback_data='new'), + InlineKeyboardButton(text="Анкета📖", callback_data='anketa')) + ikb.row(InlineKeyboardButton(text="Связь с администрацией🌐", callback_data='admin')) + + # Формируем приветственное сообщение + text: str = _( + """Добро пожаловать, {name}! + +Я ваш искусственный помощник по ролевой - {rp_name}! +Моя цель — помочь вам сориентироваться и сделать ваше вступление куда проще! +Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на клавиатуре! + +Интересный факт: +

{fact}
+""" + ).format( + url=message.from_user.url if message.from_user else "", + name=message.from_user.first_name if message.from_user else "пользователь", + rp_name=RpValue.RP_NAME, + fact=interesting_fact(), + ) + + # Отправляем сообщение + await msg_photo(update=message, text=text, file=f'assets/{CMD}.jpg', markup=ikb) diff --git a/bot/handlers/commands/settings/__init__.py b/bot/handlers/commands/settings/__init__.py new file mode 100644 index 0000000..af7d05f --- /dev/null +++ b/bot/handlers/commands/settings/__init__.py @@ -0,0 +1,19 @@ +from aiogram import Router + +from .set_description_cmd import router as set_description_cmd_router +from .set_name_cmd import router as set_name_cmd_router +from .set_widget_cmd import router as set_widget_cmd_router +from .settings_cmd import router as settings_cmd_router + +# Настройка экспорта и роутера +__all__ = ("router",) +router: Router = Router(name=__name__) + + +# Подключение роутеров +router.include_routers( +settings_cmd_router, + set_name_cmd_router, + set_description_cmd_router, + set_widget_cmd_router, +) \ No newline at end of file diff --git a/bot/handlers/commands/settings/set_description_cmd.py b/bot/handlers/commands/settings/set_description_cmd.py new file mode 100644 index 0000000..ebcca9c --- /dev/null +++ b/bot/handlers/commands/settings/set_description_cmd.py @@ -0,0 +1,173 @@ +from aiogram import Router, F, Bot +from aiogram.exceptions import TelegramAPIError, TelegramRetryAfter +from aiogram.filters import Command, CommandObject +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import StatesGroup, State +from aiogram.types import Message, CallbackQuery +from aiogram.utils.i18n import gettext as _ + +from bot.core.bots import BotInfo +from bot.filters import IsOwner +from bot.handlers.commands.settings.settings_cmd import settings_keyboard +from bot.templates import msg +from bot.utils import format_retry_time, status_clear +from configs import COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) + +# Название команды +CMD: str = "set_description".lower() + +# Роутер для обработки команды /set_description +router: Router = Router(name=f"{CMD}_cmd_router") + + +class SetBotDescriptionForm(StatesGroup): + """Состояния FSM для изменения короткого описания бота.""" + new_description: State = State() + + +async def handle_set_bot_description( + description: str, + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot +) -> None: + """ + Установка короткого описания (short description) бота с обработкой FSM и ошибок API. + + Args: + description (str): Новый текст описания (до 120 символов). + message (Message | CallbackQuery): Сообщение или callback-запрос. + state (FSMContext): Контекст FSM. + bot (Bot): Экземпляр бота. + """ + # Проверка ограничения Telegram + if len(description) > 120: + await msg( + update=message, + text=_("❌ Короткое описание бота должно быть не более 120 символов. Текущая длина: {length}").format( + length=len(description) + ), + markup=settings_keyboard(), + state=state + ) + return + + try: + # Установка нового короткого описания + await bot.set_my_short_description(short_description=description) + + # Сохраняем текущее значение в BotInfo + BotInfo.short_description = description + + # Сбрасываем состояние FSM + await state.clear() + + # Отправляем сообщение об успехе + await msg( + update=message, + text=_("✅ Короткое описание бота успешно изменено на: {description}").format( + description=description + ), + markup=settings_keyboard(), + state=state + ) + + logger.info(f"Короткое описание бота изменено на: {description}") + + except TelegramRetryAfter as e: + retry_text: str = format_retry_time(e.retry_after) + logger.warning(f"Превышен лимит запросов при смене short description. Попробуйте через {retry_text}") + await msg( + update=message, + text=_("⚠️ Слишком частая смена короткого описания!\nПопробуйте снова через: {retry_text}").format( + retry_text=retry_text + ), + markup=settings_keyboard(), + state=state + ) + + except TelegramAPIError as e: + logger.error(f"Ошибка Telegram API при изменении короткого описания: {e}") + await msg( + update=message, + text=_("❌ Ошибка Telegram API при изменении короткого описания:
{error}
").format(error=str(e)), + markup=settings_keyboard(), + state=state + ) + + except Exception as e: + logger.error(f"Непредвиденная ошибка при изменении короткого описания: {e}") + await msg( + update=message, + text=_("❌ Непредвиденная ошибка при изменении короткого описания:
{error}
").format(error=str(e)), + markup=settings_keyboard(), + state=state + ) + + +@router.callback_query(F.data.lower() == CMD, IsOwner()) +@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner()) +async def settings_cmd( + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot, + command: CommandObject | None = None +) -> None: + """ + Обработчик команды /set_description для короткого описания. + + Поддерживает: + 1. Немедленное изменение через аргумент (/set_description TEXT). + 2. Callback-запрос. + 3. FSM-ввод. + """ + current_description: str = BotInfo.description + + # Вариант 1: если пользователь передал аргумент к команде + if command and command.args: + description: str = command.args.strip() + if len(description) > 120: + await msg( + update=message, + text=_("❌ Короткое описание не должно превышать 120 символов. Текущая длина: {length}").format( + length=len(description) + ), + markup=settings_keyboard(), + state=state + ) + return + + await handle_set_bot_description(description, message, state, bot) + return + + # Вариант 2: без аргумента → включаем FSM + await status_clear(update=message, state=state) + text: str = _( + "📝 Смена короткого описания бота\n\n" + "Текущее короткое описание: {current}\n\n" + "Введите новое короткое описание (максимум 120 символов):" + ).format(current=current_description) + + await msg(update=message, text=text, markup=settings_keyboard(), state=state) + await state.set_state(SetBotDescriptionForm.new_description) + + +@router.message(SetBotDescriptionForm.new_description, IsOwner()) +async def process_new_bot_description( + message: Message, + state: FSMContext, + bot: Bot +) -> None: + """ + Обработка ввода нового короткого описания через FSM. + """ + description: str = message.text.strip() + + if not description: + await message.answer(_("❌ Пожалуйста, введите корректное короткое описание.")) + return + + await handle_set_bot_description(description, message, state, bot) diff --git a/bot/handlers/commands/settings/set_name_cmd.py b/bot/handlers/commands/settings/set_name_cmd.py new file mode 100644 index 0000000..1cb5b99 --- /dev/null +++ b/bot/handlers/commands/settings/set_name_cmd.py @@ -0,0 +1,157 @@ +from aiogram import Router, F, Bot +from aiogram.exceptions import TelegramAPIError, TelegramRetryAfter +from aiogram.filters import Command, CommandObject +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import StatesGroup, State +from aiogram.types import Message, CallbackQuery +from aiogram.utils.i18n import gettext as _ + +from bot.core.bots import BotInfo +from bot.filters import IsOwner +from bot.handlers.commands.settings.settings_cmd import settings_keyboard +from bot.templates import msg +from configs import COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) +CMD: str = "set_name".lower() +router: Router = Router(name=f"{CMD}_cmd_router") + + +class SetNameForm(StatesGroup): + new_name: State = State() + + +def format_retry_time(retry_after: int) -> str: + """Форматирование времени повторной попытки в читаемом виде""" + hours, remainder = divmod(retry_after, 3600) + minutes, seconds = divmod(remainder, 60) + + if hours > 0: + return f"{hours} часов, {minutes} минут, {seconds} секунд" + elif minutes > 0: + return f"{minutes} минут, {seconds} секунд" + else: + return f"{seconds} секунд" + + +async def handle_set_name( + new_name: str, + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot +) -> None: + """ + Установка имени бота с проверкой длины, обработкой перегрузки и логированием + """ + if len(new_name) > 64: + await msg( + update=message, + text=_("❌ Имя бота должно быть не более 64 символов. Текущая длина: {length}").format( + length=len(new_name) + ), + markup=settings_keyboard(), + state=state + ) + return + + try: + await bot.set_my_name(new_name) + BotInfo.first_name = new_name + await state.clear() + await msg( + update=message, + text=_("✅ Имя бота успешно изменено на: {new_name}").format(new_name=new_name), + markup=settings_keyboard(), + state=state + ) + logger.info(f"Имя бота изменено на: {new_name}") + + except TelegramRetryAfter as e: + retry_text: str = format_retry_time(e.retry_after) + logger.warning(f"Превышен контроль перегрузки при смене имени. Попробуйте через {retry_text}") + await msg( + update=message, + text=_("⚠️ Слишком частая смена имени!\nПопробуйте снова через: {retry_text}").format( + retry_text=retry_text + ), + markup=settings_keyboard(), + state=state + ) + + except TelegramAPIError as e: + logger.error(f"Ошибка Telegram API при изменении имени: {e}") + await msg( + update=message, + text=_("❌ Ошибка Telegram API:
{error}
").format(error=str(e)), + markup=settings_keyboard(), + state=state + ) + + except Exception as e: + logger.error(f"Непредвиденная ошибка при изменении имени: {e}") + await msg( + update=message, + text=_("❌ Непредвиденная ошибка:
{error}
").format(error=str(e)), + markup=settings_keyboard(), + state=state + ) + + +@router.callback_query(F.data.lower() == CMD, IsOwner()) +@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner()) +async def settings_cmd( + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot, + command: CommandObject | None = None +): + """ + Обработчик команды /set_name с поддержкой: + 1. Immediate установки через аргумент команды + 2. Callback query + 3. FSM ввод + """ + current_name = getattr(BotInfo, "first_name", "") or _("Не установлено") + + # Immediate установка через аргумент команды + if command and command.args: + new_name = command.args.strip() + if len(new_name) > 64: + await msg( + update=message, + text=_("❌ Имя не должно превышать 64 символа. Текущая длина: {length}").format( + length=len(new_name) + ), + markup=settings_keyboard(), + state=state + ) + return + await handle_set_name(new_name, message, state, bot) + return + + # Для callback query или пустой команды — показываем текущее имя и запускаем FSM + await state.clear() + if isinstance(message, CallbackQuery): + await message.answer() + text: str = _( + "🤖 Смена имени бота\n\n" + "Текущее имя: {current}\n\n" + "Пожалуйста, введите новое имя для бота (максимум 64 символа):" + ).format(current=current_name) + await msg(update=message, text=text, markup=settings_keyboard(), state=state) + await state.set_state(SetNameForm.new_name) + + +@router.message(SetNameForm.new_name, IsOwner()) +async def process_new_name(message: Message, state: FSMContext, bot: Bot): + """ + Обработка ввода нового имени через FSM + """ + new_name: str = message.text.strip() + + if not new_name: + await message.answer(_("❌ Пожалуйста, введите корректное имя.")) + return + + await handle_set_name(new_name, message, state, bot) diff --git a/bot/handlers/commands/settings/set_widget_cmd.py b/bot/handlers/commands/settings/set_widget_cmd.py new file mode 100644 index 0000000..3959c88 --- /dev/null +++ b/bot/handlers/commands/settings/set_widget_cmd.py @@ -0,0 +1,174 @@ +from aiogram import Router, F, Bot +from aiogram.exceptions import TelegramAPIError, TelegramRetryAfter +from aiogram.filters import Command, CommandObject +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import StatesGroup, State +from aiogram.types import Message, CallbackQuery +from aiogram.utils.i18n import gettext as _ + +from bot.core.bots import BotInfo +from bot.filters import IsOwner +from bot.handlers.commands.settings.settings_cmd import settings_keyboard +from bot.templates import msg +from bot.utils import format_retry_time, status_clear +from configs import COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) +CMD: str = "set_widget".lower() +router: Router = Router(name=f"{CMD}_cmd_router") + + +class SetWidgetForm(StatesGroup): + """Состояния FSM для изменения виджета (описания бота).""" + new_widget: State = State() + + +async def handle_set_widget( + new_widget: str, + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot +) -> None: + """ + Устанавливает новое значение виджета (описания бота). + + Args: + new_widget (str): Новый текст виджета. + message (Message | CallbackQuery): Объект сообщения или callback-запроса. + state (FSMContext): Контекст состояния FSM. + bot (Bot): Экземпляр текущего бота. + """ + # Проверка длины текста (Telegram API ограничивает description до 512 символов) + if len(new_widget) > 512: + await msg( + update=message, + text=_("❌ Виджет бота должен быть не более 512 символов. Текущая длина: {length}").format( + length=len(new_widget) + ), + markup=settings_keyboard(), + state=state + ) + return + + try: + # Устанавливаем описание через Telegram API + await bot.set_my_description(description=new_widget) + + # Сохраняем в BotInfo для локального использования + BotInfo.widget = new_widget + + # Очищаем состояние FSM + await state.clear() + + # Отправляем уведомление пользователю + await msg( + update=message, + text=_("✅ Виджет бота успешно изменён на: {new_widget}").format( + new_widget=new_widget + ), + markup=settings_keyboard(), + state=state + ) + + logger.info(f"Виджет бота изменён на: {new_widget}") + + except TelegramRetryAfter as e: + # Если запрос слишком частый + retry_text: str = format_retry_time(e.retry_after) + logger.warning(f"Превышен лимит запросов при смене виджета. Попробуйте через {retry_text}") + await msg( + update=message, + text=_("⚠️ Слишком частая смена виджета!\nПопробуйте снова через: {retry_text}").format( + retry_text=retry_text + ), + markup=settings_keyboard(), + state=state + ) + + except TelegramAPIError as e: + # Ошибка Telegram API + logger.error(f"Ошибка Telegram API при изменении виджета: {e}") + await msg( + update=message, + text=_("❌ Ошибка Telegram API при изменении виджета:
{error}
").format(error=str(e)), + markup=settings_keyboard(), + state=state + ) + + except Exception as e: + # Непредвиденная ошибка + logger.error(f"Непредвиденная ошибка при изменении виджета: {e}") + await msg( + update=message, + text=_("❌ Непредвиденная ошибка при изменении виджета:
{error}
").format(error=str(e)), + markup=settings_keyboard(), + state=state + ) + + +@router.callback_query(F.data.lower() == CMD, IsOwner()) +@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner()) +async def settings_cmd( + message: Message | CallbackQuery, + state: FSMContext, + bot: Bot, + command: CommandObject | None = None +) -> None: + """ + Обработчик команды /set_widget. + + Поддерживает: + 1. Немедленное изменение через аргумент команды (/set_widget TEXT). + 2. Callback-запрос. + 3. FSM ввод. + """ + # Получаем текущее значение виджета + current_widget: str = BotInfo.short_description + + # Вариант 1: пользователь ввёл аргумент сразу (/set_widget TEXT) + if command and command.args: + new_widget: str = command.args.strip() + if len(new_widget) > 512: + await msg( + update=message, + text=_("❌ Виджет не должен превышать 512 символов. Текущая длина: {length}").format( + length=len(new_widget) + ), + markup=settings_keyboard(), + state=state + ) + return + + await handle_set_widget(new_widget, message, state, bot) + return + + # Вариант 2: Callback query или пустая команда → запускаем FSM + await status_clear(update=message, state=state) + text: str = _( + "📝 Смена виджета бота\n\n" + "Текущий виджет: {current}\n\n" + "Пожалуйста, введите новый виджет для бота (максимум 512 символов):" + ).format(current=current_widget) + + await msg(update=message, text=text, markup=settings_keyboard(), state=state) + await state.set_state(SetWidgetForm.new_widget) + + +@router.message(SetWidgetForm.new_widget, IsOwner()) +async def process_new_widget( + message: Message, + state: FSMContext, + bot: Bot +) -> None: + """ + Обрабатывает ввод нового текста виджета через FSM. + """ + new_widget: str = message.text.strip() + + # Проверяем, что пользователь что-то ввёл + if not new_widget: + await message.answer(_("❌ Пожалуйста, введите корректный виджет.")) + return + + await handle_set_widget(new_widget, message, state, bot) diff --git a/bot/handlers/commands/settings/settings_cmd.py b/bot/handlers/commands/settings/settings_cmd.py new file mode 100644 index 0000000..4894044 --- /dev/null +++ b/bot/handlers/commands/settings/settings_cmd.py @@ -0,0 +1,48 @@ +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.fsm.context import FSMContext +from aiogram.types import Message, CallbackQuery, InlineKeyboardButton +from aiogram.utils.i18n import gettext as _ +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from bot.core.bots import BotInfo +from bot.filters import IsOwner +from bot.templates import msg +from bot.utils import status_clear +from configs import COMMANDS + +# Настройки экспорта и роутера +__all__ = ("router", "settings_keyboard",) +CMD: str = "settings".lower() +router: Router = Router(name=f"{CMD}_cmd_router") + + +def settings_keyboard() -> InlineKeyboardBuilder: + """Клавиатура настроек""" + ikb: InlineKeyboardBuilder = InlineKeyboardBuilder() + ikb.row(InlineKeyboardButton(text="🔙 Вернуться", callback_data="settings")) + return ikb + + +@router.callback_query(F.data.lower() == CMD, IsOwner()) +@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner()) +async def settings_cmd(message: Message | CallbackQuery, state: FSMContext) -> None: + """Обработчик команды /settings""" + await status_clear(update=message, state=state) + + # Создание инлайн-клавиатуры + ikb: InlineKeyboardBuilder = InlineKeyboardBuilder() + ikb.row(InlineKeyboardButton(text="Имя бота⚜️", callback_data='set_name')) + ikb.row(InlineKeyboardButton(text="Описание бота📝", callback_data='set_description')) + ikb.row(InlineKeyboardButton(text="Виджет🧩", callback_data='set_widget')) + ikb.row(InlineKeyboardButton(text="Назад◀️", callback_data='menu')) + + # Формируем приветственное сообщение + text: str = _(""" +⚙️ Настройки +""" + ).format( + ) + + # Отправляем сообщение + await msg(update=message, text=text, markup=ikb, state=state) diff --git a/bot/handlers/commands/users/__init__.py b/bot/handlers/commands/users/__init__.py new file mode 100644 index 0000000..d3fab41 --- /dev/null +++ b/bot/handlers/commands/users/__init__.py @@ -0,0 +1,33 @@ +from aiogram import Router + +from .start_cmd import router as start_cmd_router +from .listwords import router as listwords_cmd_router +from .word import router as word_cmd_router +from .slience import router as slice_router +from .conflict import router as conflict_router +from .stats import router as stats_router +from .report import router as report_router +from .admins import router as admin_router +from .notifications import router as notifications_router +from .id import router as id_router +from .emoji import router as emoji_router + +# Настройка экспорта и роутера +__all__ = ("router",) +router: Router = Router(name=__name__) + + +# Подключение роутеров +router.include_routers( +notifications_router, +report_router, +admin_router, + start_cmd_router, +listwords_cmd_router, +word_cmd_router, +slice_router, +conflict_router, +stats_router, +id_router, +emoji_router, +) diff --git a/bot/handlers/commands/users/admins.py b/bot/handlers/commands/users/admins.py new file mode 100644 index 0000000..61cc8e3 --- /dev/null +++ b/bot/handlers/commands/users/admins.py @@ -0,0 +1,434 @@ +""" +Обработчики команд управления администраторами +""" +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message, CallbackQuery +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from bot.filters.admin import IsSuperAdmin +from configs import settings, COMMANDS +from database import get_manager +from middleware.loggers import logger +from bot.utils.decorators import log_action + +__all__ = ("router",) + +router: Router = Router(name="admin_management_router") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def parse_user_id(text: str, command: str) -> tuple[bool, str | int]: + """ + Парсит ID пользователя из команды. + + Args: + text: Полный текст сообщения + command: Название команды + + Returns: + (success, result): result это либо user_id (int), либо текст ошибки (str) + """ + parts = text.split(maxsplit=1) + + if len(parts) < 2: + return False, f"❌ Использование: /{command} " + + user_id_str = parts[1].strip() + + # Валидация ID + try: + user_id = int(user_id_str) + + if user_id <= 0: + return False, "❌ ID должен быть положительным числом" + + if user_id > 9999999999: # Максимальный Telegram ID + return False, "❌ Некорректный ID пользователя" + + return True, user_id + + except ValueError: + return False, "❌ ID должен быть числом" + + +def format_admin_info(user_id: int, username: str | None = None) -> str: + """Форматирует информацию об админе""" + if username: + return f"{user_id} (@{username})" + return f"{user_id}" + + +def get_refresh_admins_kb(): + """Клавиатура для обновления списка админов""" + ikb = InlineKeyboardBuilder() + ikb.button(text="🔄 Обновить", callback_data="listadmins:refresh") + ikb.button(text="➕ Добавить", callback_data="admin:help_add") + ikb.adjust(2) + return ikb.as_markup() + + +# ================= ДОБАВЛЕНИЕ АДМИНИСТРАТОРА ================= + +@router.message(Command(*COMMANDS.get("addadmin", ["addadmin"]), prefix=settings.PREFIX, ignore_case=True), + IsSuperAdmin()) +@log_action(action_name="ADD_ADMIN", log_args=True) +async def add_admin_cmd(message: Message) -> None: + """ + Добавляет нового администратора бота. + + Доступно только владельцам бота (OWNER_ID). + + Использование: /addadmin + Пример: /addadmin 123456789 + """ + success, result = parse_user_id(message.text, "addadmin") + + if not success: + await message.answer(result, parse_mode="HTML") + return + + user_id = result + + # Проверка: нельзя добавить самого себя + if user_id == message.from_user.id: + await message.answer( + "⚠️ Вы уже владелец бота\n\n" + "Вам не нужно добавлять себя в администраторы", + parse_mode="HTML" + ) + return + + # Проверка: нельзя добавить другого владельца + if user_id in settings.OWNER_ID: + await message.answer( + "⚠️ Этот пользователь уже владелец бота\n\n" + "Владельцы имеют полные права автоматически", + parse_mode="HTML" + ) + return + + manager = get_manager() + + try: + # Проверяем, уже админ ли + is_already_admin = await manager.is_admin(user_id) + + if is_already_admin: + await message.answer( + f"⚠️ Пользователь {format_admin_info(user_id)} уже является администратором", + parse_mode="HTML" + ) + return + + # Добавляем администратора + added = await manager.add_admin( + user_id=user_id, + added_by=message.from_user.id + ) + + if added: + text = ( + f"✅ Администратор добавлен\n\n" + f"👤 ID: {format_admin_info(user_id)}\n" + f"👑 Добавил: {format_admin_info(message.from_user.id, message.from_user.username)}\n\n" + f"📋 Права администратора:\n" + f"├─ Управление банвордами\n" + f"├─ Просмотр статистики\n" + f"├─ Активация режимов модерации\n" + f"└─ Все команды бота\n\n" + f"⚠️ Не может управлять другими админами\n" + f"Список админов: /listadmins" + ) + + logger.info( + f"Администратор добавлен: {user_id} (добавил: {message.from_user.id})", + log_type="ADMIN_MGMT" + ) + else: + text = "❌ Ошибка добавления администратора\n\nПопробуйте позже" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления администратора: {e}", log_type="ADMIN_MGMT") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +# ================= УДАЛЕНИЕ АДМИНИСТРАТОРА ================= + +@router.message(Command(*COMMANDS.get("remadmin", ["remadmin"]), prefix=settings.PREFIX, ignore_case=True), + IsSuperAdmin()) +@log_action(action_name="REMOVE_ADMIN", log_args=True) +async def remove_admin_cmd(message: Message) -> None: + """ + Удаляет администратора бота. + + Доступно только владельцам бота (OWNER_ID). + + Использование: /remadmin + Пример: /remadmin 123456789 + """ + success, result = parse_user_id(message.text, "remadmin") + + if not success: + await message.answer(result, parse_mode="HTML") + return + + user_id = result + + # Проверка: нельзя удалить владельца + if user_id in settings.OWNER_ID: + await message.answer( + "⚠️ Нельзя удалить владельца\n\n" + "Владельцы имеют права постоянно", + parse_mode="HTML" + ) + return + + # Проверка: нельзя удалить самого себя (если вы владелец) + if user_id == message.from_user.id: + await message.answer( + "⚠️ Нельзя удалить самого себя", + parse_mode="HTML" + ) + return + + manager = get_manager() + + try: + # Проверяем, является ли администратором + is_admin = await manager.is_admin(user_id) + + if not is_admin: + await message.answer( + f"⚠️ Пользователь {format_admin_info(user_id)} не является администратором", + parse_mode="HTML" + ) + return + + # Удаляем администратора + removed = await manager.remove_admin(user_id=user_id) + + if removed: + text = ( + f"🗑 Администратор удалён\n\n" + f"👤 ID: {format_admin_info(user_id)}\n" + f"👑 Удалил: {format_admin_info(message.from_user.id, message.from_user.username)}\n\n" + f"⚠️ Пользователь больше не имеет доступа к командам бота" + ) + + logger.info( + f"Администратор удалён: {user_id} (удалил: {message.from_user.id})", + log_type="ADMIN_MGMT" + ) + else: + text = "❌ Ошибка удаления администратора\n\nПопробуйте позже" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления администратора: {e}", log_type="ADMIN_MGMT") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") + + +# ================= СПИСОК АДМИНИСТРАТОРОВ ================= + +@router.callback_query(F.data == "listadmins:refresh") +@router.message(Command(*COMMANDS.get("listadmins", ["listadmins"]), prefix=settings.PREFIX, ignore_case=True), + IsSuperAdmin()) +@log_action(action_name="LIST_ADMINS") +async def list_admins_cmd(update: Message | CallbackQuery) -> None: + """ + Показывает список всех администраторов бота. + + Доступно только владельцам бота (OWNER_ID). + + Использование: /listadmins + """ + # Определяем тип update + if isinstance(update, CallbackQuery): + message = update.message + is_callback = True + else: + message = update + is_callback = False + + manager = get_manager() + + try: + # Получаем всех админов из БД + db_admins = await manager.repo.get_admins() + + # Получаем статистику + stats = await manager.get_stats() + + # === ФОРМИРУЕМ ВЫВОД === + + output = "👥 СПИСОК АДМИНИСТРАТОРОВ\n\n" + + # Владельцы (OWNER_ID) + output += "👑 Владельцы бота (полные права):\n" + for owner_id in settings.OWNER_ID: + output += f"├─ {owner_id}\n" + output += "\n" + + # Администраторы из БД + if db_admins: + output += f"⚙️ Администраторы ({len(db_admins)}):\n" + + for admin_id in sorted(db_admins): + output += f"├─ {admin_id}\n" + + output += "\n" + output += "📋 Права администраторов:\n" + output += "├─ Управление банвордами\n" + output += "├─ Просмотр статистики\n" + output += "├─ Активация режимов модерации\n" + output += "└─ Все команды бота (кроме управления админами)\n\n" + else: + output += "⚙️ Администраторы:\n" + output += "└─ Нет дополнительных администраторов\n\n" + + # Общая статистика + total_admins = len(settings.OWNER_ID) + len(db_admins) + output += f"📊 Итого: {total_admins} администратор(ов)\n\n" + + # Команды управления + output += "🔧 Управление:\n" + output += "• /addadmin ID — добавить админа\n" + output += "• /remadmin ID — удалить админа\n\n" + + output += "💡 Только владельцы могут управлять администраторами" + + # Клавиатура + keyboard = get_refresh_admins_kb() + + # Отправка + if is_callback: + await message.edit_text( + text=output, + parse_mode="HTML", + reply_markup=keyboard + ) + await update.answer("✅ Список обновлён") + else: + await message.answer( + text=output, + parse_mode="HTML", + reply_markup=keyboard + ) + + except Exception as e: + logger.error(f"Ошибка получения списка администраторов: {e}", log_type="ADMIN_MGMT") + + error_text = "❌ Ошибка загрузки списка\n\nПопробуйте позже" + + if is_callback: + await update.answer("❌ Ошибка загрузки", show_alert=True) + else: + await message.answer(error_text, parse_mode="HTML") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ CALLBACK ================= + +@router.callback_query(F.data == "admin:help_add") +async def admin_help_add_callback(callback: CallbackQuery) -> None: + """Показывает помощь по добавлению админа""" + text = ( + "➕ Как добавить администратора?\n\n" + "1️⃣ Узнайте Telegram ID пользователя\n" + " • Используйте бота @userinfobot\n" + " • Или попросите пользователя написать /start\n\n" + "2️⃣ Выполните команду:\n" + " /addadmin ID\n\n" + "Пример:\n" + "/addadmin 123456789" + ) + + await callback.answer() + await callback.message.answer(text, parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("adminhelp", ["adminhelp"]), prefix=settings.PREFIX, ignore_case=True), + IsSuperAdmin()) +async def admin_help_cmd(message: Message) -> None: + """ + Показывает подробную справку по управлению администраторами. + + Использование: /adminhelp + """ + text = ( + "👥 УПРАВЛЕНИЕ АДМИНИСТРАТОРАМИ\n\n" + "🔐 Уровни доступа:\n\n" + "👑 Владельцы (OWNER_ID):\n" + "├─ Все права администратора\n" + "├─ Управление другими админами\n" + "└─ Указываются в конфигурации\n\n" + "⚙️ Администраторы:\n" + "├─ Управление банвордами\n" + "├─ Просмотр статистики\n" + "├─ Активация режимов модерации\n" + "└─ НЕ могут управлять админами\n\n" + "📝 Команды:\n" + "• /listadmins — список всех админов\n" + "• /addadmin ID — добавить админа\n" + "• /remadmin ID — удалить админа\n\n" + "💡 Как узнать ID пользователя?\n" + "• Используйте бота @userinfobot\n" + "• Попросите пользователя написать боту\n" + "• ID отображается в логах бота\n\n" + "⚠️ Важно:\n" + "├─ Нельзя удалить владельца\n" + "├─ Нельзя удалить самого себя\n" + "└─ Все действия логируются" + ) + + await message.answer(text, parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("checkadmin", ["checkadmin"]), prefix=settings.PREFIX, ignore_case=True), + IsSuperAdmin()) +@log_action(action_name="CHECK_ADMIN") +async def check_admin_cmd(message: Message) -> None: + """ + Проверяет, является ли пользователь администратором. + + Использование: /checkadmin + """ + success, result = parse_user_id(message.text, "checkadmin") + + if not success: + await message.answer(result, parse_mode="HTML") + return + + user_id = result + manager = get_manager() + + try: + # Проверяем статус + is_owner = user_id in settings.OWNER_ID + is_db_admin = await manager.is_admin(user_id) + + text = f"🔍 Проверка пользователя\n\n" + text += f"👤 ID: {user_id}\n\n" + + if is_owner: + text += "👑 Статус: Владелец бота\n" + text += "✅ Полные права администратора\n" + text += "✅ Может управлять админами" + elif is_db_admin: + text += "⚙️ Статус: Администратор\n" + text += "✅ Доступ к командам бота\n" + text += "❌ Не может управлять админами" + else: + text += "👤 Статус: Обычный пользователь\n" + text += "❌ Нет прав администратора\n\n" + text += f"Добавить в админы: /addadmin {user_id}" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка проверки администратора: {e}", log_type="ADMIN_MGMT") + await message.answer("❌ Ошибка проверки", parse_mode="HTML") 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") diff --git a/bot/handlers/commands/users/emoji.py b/bot/handlers/commands/users/emoji.py new file mode 100644 index 0000000..807a908 --- /dev/null +++ b/bot/handlers/commands/users/emoji.py @@ -0,0 +1,215 @@ +""" +Обработчик команды /emoji для извлечения ID премиум эмодзи +""" +from aiogram import Router +from aiogram.filters import Command +from aiogram.types import Message +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from bot.filters.admin import IsAdmin +from configs import settings, COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) + +router: Router = Router(name="emoji_extractor_router") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def extract_custom_emojis(message: Message) -> list[dict]: + """ + Извлекает все кастомные эмодзи из сообщения. + + Args: + message: Сообщение для анализа + + Returns: + Список словарей с информацией об эмодзи + """ + if not message.entities and not message.caption_entities: + return [] + + # Определяем текст и entities + text = message.text or message.caption + entities = message.entities or message.caption_entities + + if not text or not entities: + return [] + + custom_emojis = [] + + for entity in entities: + if entity.type == "custom_emoji": + # Извлекаем символ эмодзи + emoji_char = text[entity.offset:entity.offset + entity.length] + + custom_emojis.append({ + "char": emoji_char, + "id": entity.custom_emoji_id, + "offset": entity.offset + }) + + return custom_emojis + + +def format_emoji_html(emoji_char: str, emoji_id: str) -> str: + """ + Форматирует эмодзи в HTML-тег. + + Args: + emoji_char: Символ эмодзи (fallback) + emoji_id: ID кастомного эмодзи + + Returns: + HTML-строка + """ + return f'{emoji_char}' + + +def escape_html(text: str) -> str: + """Экранирует HTML символы""" + return ( + text.replace("&", "&") + .replace("<", "<") + .replace(">", ">") + ) + + +# ================= КОМАНДА /EMOJI ================= + +@router.message( + Command(*COMMANDS.get("emoji", ["emoji"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin() +) +async def emoji_extractor_cmd(message: Message) -> None: + """ + Извлекает кастомные эмодзи из сообщения. + + Доступно только администраторам. + + Использование: /emoji (в ответ на сообщение) + """ + # Проверяем, что команда в ответ на сообщение + if not message.reply_to_message: + await message.answer( + "❌ Используйте команду в ответ на сообщение\n\n" + "📝 Как использовать:\n" + "1. Ответьте на сообщение с премиум эмодзи\n" + "2. Напишите /emoji\n\n" + "💡 Бот извлечёт все кастомные эмодзи и покажет HTML-код", + parse_mode="HTML" + ) + return + + replied_message = message.reply_to_message + + # Извлекаем кастомные эмодзи + custom_emojis = extract_custom_emojis(replied_message) + + if not custom_emojis: + # Нет кастомных эмодзи + await message.answer( + "⚠️ Кастомные эмодзи не найдены\n\n" + "В этом сообщении нет премиум эмодзи.\n\n" + "💡 Попробуйте ответить на сообщение с анимированными эмодзи", + parse_mode="HTML" + ) + return + + # === ФОРМИРУЕМ ОТВЕТ === + + output = f"✨ НАЙДЕНО ЭМОДЗИ: {len(custom_emojis)}\n\n" + + for idx, emoji_data in enumerate(custom_emojis, 1): + emoji_char = emoji_data["char"] + emoji_id = emoji_data["id"] + + output += f"{idx}. Эмодзи: {emoji_char}\n" + output += f"📋 ID: {emoji_id}\n\n" + + # HTML-код (экранированный для отображения) + html_code = format_emoji_html(emoji_char, emoji_id) + html_escaped = escape_html(html_code) + + output += f"📝 HTML-код:\n" + output += f"{html_escaped}\n\n" + + # Пример использования + output += f"🎨 Превью: {html_code}\n" + + if idx < len(custom_emojis): + output += "\n" + "─" * 30 + "\n\n" + + output += "💡 Скопируйте HTML-код и используйте в своих сообщениях" + + # Создаём клавиатуру + ikb = InlineKeyboardBuilder() + ikb.button(text="✖️ Закрыть", callback_data="emoji_close") + + # Отправляем + try: + await message.answer( + text=output, + parse_mode="HTML", + reply_markup=ikb.as_markup() + ) + + logger.info( + f"Извлечено {len(custom_emojis)} кастомных эмодзи админом {message.from_user.id}", + log_type="EMOJI_EXTRACT" + ) + + except Exception as e: + logger.error(f"Ошибка отправки эмодзи: {e}", log_type="ERROR") + await message.answer( + "❌ Ошибка извлечения эмодзи\n\n" + "Попробуйте позже или обратитесь к разработчику.", + parse_mode="HTML" + ) + + +# ================= ОБРАБОТЧИК КНОПКИ ЗАКРЫТИЯ ================= + +@router.callback_query(lambda c: c.data == "emoji_close", IsAdmin()) +async def emoji_close_callback(callback) -> None: + """Закрывает сообщение с эмодзи""" + try: + await callback.message.delete() + await callback.answer("✅ Закрыто") + except Exception as e: + logger.error(f"Ошибка удаления сообщения с эмодзи: {e}", log_type="ERROR") + await callback.answer("❌ Не удалось удалить", show_alert=True) + + +# ================= ДОПОЛНИТЕЛЬНАЯ КОМАНДА /EMOJIHELP ================= + +@router.message( + Command(*COMMANDS.get("emojihelp", ["emojihelp"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin() +) +async def emoji_help_cmd(message: Message) -> None: + """ + Справка по работе с кастомными эмодзи. + """ + text = ( + "🎨 РАБОТА С КАСТОМНЫМИ ЭМОДЗИ\n\n" + "📝 Команда /emoji\n" + "Извлекает ID премиум эмодзи из сообщения\n\n" + "🔧 Как использовать:\n" + "1️⃣ Ответьте на сообщение с эмодзи\n" + "2️⃣ Напишите /emoji\n" + "3️⃣ Скопируйте HTML-код\n\n" + "💻 Формат HTML-кода:\n" + "<tg-emoji emoji-id=\"ID\">fallback</tg-emoji>\n\n" + "📌 Пример использования в коде:\n" + "text = 'Привет <tg-emoji emoji-id=\"5368324170671202286\">👍</tg-emoji>'\n" + "await message.answer(text, parse_mode=\"HTML\")\n\n" + "⚠️ Важно:\n" + "├─ Используйте parse_mode=\"HTML\"\n" + "├─ Пользователи без Premium видят fallback\n" + "└─ Работает только с кастомными эмодзи\n\n" + "💡 Попробуйте отправить эмодзи и ответить командой /emoji" + ) + + await message.answer(text, parse_mode="HTML") diff --git a/bot/handlers/commands/users/id.py b/bot/handlers/commands/users/id.py new file mode 100644 index 0000000..a23fe07 --- /dev/null +++ b/bot/handlers/commands/users/id.py @@ -0,0 +1,221 @@ +""" +Обработчик команды /id для получения информации о пользователе +""" +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message, CallbackQuery +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from configs import settings, COMMANDS +from middleware.loggers import logger + +__all__ = ("router",) + +router: Router = Router(name="user_id_router") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def get_close_keyboard(): + """Создаёт клавиатуру с кнопкой закрытия""" + ikb = InlineKeyboardBuilder() + ikb.button(text="✖️ Закрыть", callback_data="id_close") + return ikb.as_markup() + + +# ================= КОМАНДА /ID ================= + +@router.message(Command(*COMMANDS.get("id", ["id"]), prefix=settings.PREFIX, ignore_case=True)) +async def id_cmd(message: Message) -> None: + """ + Показывает информацию о вашем Telegram аккаунте. + + Доступно всем пользователям. + + Использование: /id + """ + user = message.from_user + + if not user: + await message.answer("❌ Не удалось получить информацию о пользователе") + return + + # === ФОРМИРУЕМ ИНФОРМАЦИЮ === + + output = "👤 ИНФОРМАЦИЯ О ВАС\n\n" + + # Имя + full_name_parts = [] + if user.first_name: + full_name_parts.append(user.first_name) + if user.last_name: + full_name_parts.append(user.last_name) + + full_name = " ".join(full_name_parts) if full_name_parts else "Не указано" + output += f"📝 Имя: {full_name}\n" + + # Username + if user.username: + output += f"🔗 Username: @{user.username}\n" + else: + output += f"🔗 Username: не установлен\n" + + # ID + output += f"🆔 ID: {user.id}\n\n" + + # Тип аккаунта + if user.is_bot: + output += f"🤖 Тип: Бот\n" + elif user.is_premium: + output += f"⭐️ Тип: Premium пользователь\n" + else: + output += f"👥 Тип: Обычный пользователь\n" + + # Дополнительная информация + output += "\n📊 Дополнительно:\n" + + # Язык + if user.language_code: + language_names = { + 'ru': '🇷🇺 Русский', + 'en': '🇬🇧 English', + 'uk': '🇺🇦 Українська', + 'de': '🇩🇪 Deutsch', + 'es': '🇪🇸 Español', + 'fr': '🇫🇷 Français', + 'it': '🇮🇹 Italiano', + 'pt': '🇵🇹 Português', + } + language = language_names.get(user.language_code, f"🌐 {user.language_code.upper()}") + output += f"├─ Язык: {language}\n" + + # Информация о чате + if message.chat.type == "private": + output += f"├─ Чат: 💬 Личные сообщения\n" + else: + chat_title = message.chat.title or "Без названия" + chat_types = { + "group": "👥 Группа", + "supergroup": "👥 Супергруппа", + "channel": "📢 Канал" + } + chat_type = chat_types.get(message.chat.type, "💬 Чат") + output += f"├─ Чат: {chat_type}\n" + output += f"├─ Название: {chat_title}\n" + output += f"├─ Chat ID: {message.chat.id}\n" + + # Получаем количество участников (только для групп) + try: + member_count = await message.bot.get_chat_member_count(message.chat.id) + output += f"├─ Участников: {member_count}\n" + except Exception as e: + logger.debug(f"Не удалось получить количество участников: {e}", log_type="USER_ID") + + # Message ID + output += f"└─ Message ID: {message.message_id}\n\n" + + # Подсказка + output += "💡 Эту информацию видите только вы" + + # Клавиатура + keyboard = get_close_keyboard() + + # Отправляем + try: + await message.answer( + text=output, + parse_mode="HTML", + reply_markup=keyboard + ) + + logger.debug(f"Команда /id от пользователя {user.id}", log_type="USER_ID") + + except Exception as e: + logger.error(f"Ошибка отправки информации о пользователе: {e}", log_type="ERROR") + await message.answer("❌ Произошла ошибка при получении информации") + + +# ================= ОБРАБОТЧИК КНОПКИ ЗАКРЫТИЯ ================= + +@router.callback_query(F.data == "id_close") +async def id_close_callback(callback: CallbackQuery) -> None: + """Закрывает (удаляет) сообщение с информацией""" + try: + await callback.message.delete() + await callback.answer("✅ Закрыто") + except Exception as e: + logger.error(f"Ошибка удаления сообщения ID: {e}", log_type="ERROR") + await callback.answer("❌ Не удалось удалить сообщение", show_alert=True) + + +# ================= КОМАНДА /MYID (АЛЬТЕРНАТИВА) ================= + +@router.message(Command(*COMMANDS.get("myid", ["myid"]), prefix=settings.PREFIX, ignore_case=True)) +async def myid_cmd(message: Message) -> None: + """ + Быстрый просмотр вашего ID. + + Использование: /myid + """ + user = message.from_user + + if not user: + await message.answer("❌ Не удалось получить ID") + return + + # Короткий ответ + text = f"🆔 Ваш ID: {user.id}" + + if user.username: + text += f"\n🔗 Username: @{user.username}" + + await message.answer(text, parse_mode="HTML") + + +# ================= КОМАНДА /CHATID ================= + +@router.message(Command(*COMMANDS.get("chatid", ["chatid"]), prefix=settings.PREFIX, ignore_case=True)) +async def chatid_cmd(message: Message) -> None: + """ + Показывает ID текущего чата. + + Использование: /chatid + """ + chat = message.chat + + output = "💬 ИНФОРМАЦИЯ О ЧАТЕ\n\n" + + # Тип чата + chat_types = { + "private": "💬 Личные сообщения", + "group": "👥 Группа", + "supergroup": "👥 Супергруппа", + "channel": "📢 Канал" + } + chat_type = chat_types.get(chat.type, "💬 Чат") + + output += f"📝 Тип: {chat_type}\n" + + if chat.title: + output += f"📌 Название: {chat.title}\n" + + if chat.username: + output += f"🔗 Username: @{chat.username}\n" + + output += f"🆔 Chat ID: {chat.id}\n" + + # Дополнительная информация для групп + if chat.type in ["group", "supergroup"]: + try: + member_count = await message.bot.get_chat_member_count(chat.id) + output += f"👥 Участников: {member_count}\n" + except Exception as e: + logger.debug(f"Не удалось получить количество участников: {e}", log_type="USER_ID") + + keyboard = get_close_keyboard() + + await message.answer( + text=output, + parse_mode="HTML", + reply_markup=keyboard + ) diff --git a/bot/handlers/commands/users/listwords.py b/bot/handlers/commands/users/listwords.py new file mode 100644 index 0000000..2673f4a --- /dev/null +++ b/bot/handlers/commands/users/listwords.py @@ -0,0 +1,238 @@ +""" +Обработчик команды /listwords - отображение всех правил модерации +""" +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message, CallbackQuery +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from bot.filters.admin import IsAdmin +from configs import settings, COMMANDS +from database import get_manager +from middleware.loggers import logger +from bot.utils.decorators import log_action + +__all__ = ("router",) +CMD: str = "list" +router: Router = Router(name="listwords_cmd_router") + + +def get_refresh_kb(page: int = 0): + """Клавиатура с кнопкой обновления""" + ikb = InlineKeyboardBuilder() + ikb.button(text="🔄 Обновить", callback_data=f"listwords:refresh:{page}") + ikb.button(text="📊 Статистика", callback_data="stats") + ikb.adjust(2) + return ikb.as_markup() + + +async def format_banwords_list(page: int = 0) -> str: + """ + Форматирует список всех банвордов с разбивкой по типам. + + Args: + page: Номер страницы (для будущей пагинации) + + Returns: + Отформатированная строка со всеми правилами + """ + manager = get_manager() + + # Получаем все данные из БД + try: + # Используем существующий метод get_all_words_list() + data = await manager.get_all_words_list() + stats = await manager.get_stats() + + # Извлекаем данные из словаря + permanent_words = list(data.get('substring', set())) + permanent_lemmas = list(data.get('lemma', set())) + permanent_parts = list(data.get('part', set())) + temp_words = list(data.get('temp_substring', set())) + temp_lemmas = list(data.get('temp_lemma', set())) + conflict_words = list(data.get('conflict_substring', set())) + conflict_lemmas = list(data.get('conflict_lemma', set())) + exceptions = list(data.get('whitelist', set())) + + except Exception as e: + logger.error(f"Ошибка получения данных из БД: {e}", log_type="LISTWORDS") + return "❌ Ошибка загрузки данных из базы" + + # === ФОРМИРУЕМ ВЫВОД === + + output = "📋 СПИСОК ПРАВИЛ МОДЕРАЦИИ\n\n" + + # Статистика + total_count = ( + len(permanent_words) + len(permanent_lemmas) + len(permanent_parts) + + len(temp_words) + len(temp_lemmas) + + len(conflict_words) + len(conflict_lemmas) + ) + + output += f"📊 Общая статистика:\n" + output += f"├─ Всего правил: {total_count}\n" + output += f"├─ Исключений: {len(exceptions)}\n" + output += f"├─ Удалений за всё время: {stats.get('total_deletions', 0)}\n" + output += f"└─ Администраторов: {stats.get('admins', 0)}\n\n" + + # === ПОСТОЯННЫЕ ПРАВИЛА === + if permanent_words or permanent_lemmas or permanent_parts: + output += "🔴 ПОСТОЯННЫЕ ПРАВИЛА:\n\n" + + if permanent_words: + output += f"📝 Подстроки ({len(permanent_words)}):\n" + words_str = ', '.join([f"{w}" for w in sorted(permanent_words)[:20]]) + if len(permanent_words) > 20: + words_str += f" ... (+{len(permanent_words) - 20} ещё)" + output += f"{words_str}\n\n" + + if permanent_lemmas: + output += f"🔤 Леммы ({len(permanent_lemmas)}):\n" + lemmas_str = ', '.join([f"{w}" for w in sorted(permanent_lemmas)[:20]]) + if len(permanent_lemmas) > 20: + lemmas_str += f" ... (+{len(permanent_lemmas) - 20} ещё)" + output += f"{lemmas_str}\n\n" + + if permanent_parts: + output += f"🧩 Части ({len(permanent_parts)}):\n" + parts_str = ', '.join([f"{w}" for w in sorted(permanent_parts)[:20]]) + if len(permanent_parts) > 20: + parts_str += f" ... (+{len(permanent_parts) - 20} ещё)" + output += f"{parts_str}\n\n" + + # === ВРЕМЕННЫЕ ПРАВИЛА === + if temp_words or temp_lemmas: + output += "⏱ ВРЕМЕННЫЕ ПРАВИЛА:\n\n" + + if temp_words: + output += f"📝 Временные подстроки ({len(temp_words)}):\n" + # Для временных слов нужна дополнительная информация о времени истечения + # Пока просто выводим список + words_str = ', '.join([f"{w}" for w in sorted(temp_words)[:15]]) + if len(temp_words) > 15: + words_str += f" ... (+{len(temp_words) - 15} ещё)" + output += f"{words_str}\n\n" + + if temp_lemmas: + output += f"🔤 Временные леммы ({len(temp_lemmas)}):\n" + lemmas_str = ', '.join([f"{w}" for w in sorted(temp_lemmas)[:15]]) + if len(temp_lemmas) > 15: + lemmas_str += f" ... (+{len(temp_lemmas) - 15} ещё)" + output += f"{lemmas_str}\n\n" + + # === КОНФЛИКТНЫЕ ПРАВИЛА === + if conflict_words or conflict_lemmas: + output += "⚔️ КОНФЛИКТНЫЕ ПРАВИЛА:\n" + output += "(работают только в режиме /stopconflict)\n\n" + + if conflict_words: + output += f"📝 Конфликтные слова ({len(conflict_words)}):\n" + words_str = ', '.join([f"{w}" for w in sorted(conflict_words)[:15]]) + if len(conflict_words) > 15: + words_str += f" ... (+{len(conflict_words) - 15} ещё)" + output += f"{words_str}\n\n" + + if conflict_lemmas: + output += f"🔤 Конфликтные леммы ({len(conflict_lemmas)}):\n" + lemmas_str = ', '.join([f"{w}" for w in sorted(conflict_lemmas)[:15]]) + if len(conflict_lemmas) > 15: + lemmas_str += f" ... (+{len(conflict_lemmas) - 15} ещё)" + output += f"{lemmas_str}\n\n" + + # === ИСКЛЮЧЕНИЯ (WHITELIST) === + if exceptions: + output += f"✅ ИСКЛЮЧЕНИЯ ({len(exceptions)}):\n" + exc_str = ', '.join([f"{exceptions}" for w in sorted(exceptions)[:15]]) + if len(exceptions) > 15: + exc_str += f" ... (+{len(exceptions) - 15} ещё)" + output += f"{exc_str}\n\n" + + # === АКТИВНЫЕ РЕЖИМЫ === + active_modes = [] + + if await manager.is_silence_active(): + active_modes.append("🔇 Режим тишины") + + if await manager.is_conflict_active(): + active_modes.append("⚔️ Режим антиконфликта") + + if active_modes: + output += "🔴 АКТИВНЫЕ РЕЖИМЫ:\n" + for mode in active_modes: + output += f"{mode}\n" + output += "\n" + + # === ПУСТОЙ СПИСОК === + if total_count == 0: + output = ( + "📋 СПИСОК ПРАВИЛ МОДЕРАЦИИ\n\n" + "⚠️ Правила модерации не настроены\n\n" + "Используйте команды добавления:\n" + "• /addword — добавить подстроку\n" + "• /addlemma — добавить лемму\n" + "• /addpart — добавить часть\n\n" + "📖 Подробнее: /start" + ) + + # Ограничение длины (Telegram limit 4096) + if len(output) > 4000: + output = output[:3950] + "\n\n... список обрезан, слишком много правил" + + return output + + +@router.callback_query(F.data.startswith("listwords:refresh")) +@router.message(Command(*COMMANDS[CMD], prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="LISTWORDS_COMMAND") +async def listwords_cmd(update: Message | CallbackQuery) -> None: + """ + Обработчик команды /listwords. + Отображает список всех правил модерации с разбивкой по категориям. + + Доступно только администраторам. + + Args: + update: Message или CallbackQuery + """ + # Определяем тип update + if isinstance(update, CallbackQuery): + message = update.message + is_callback = True + # Извлекаем номер страницы из callback_data + try: + page = int(update.data.split(":")[-1]) + except: + page = 0 + else: + message = update + is_callback = False + page = 0 + + # Формируем список + try: + text = await format_banwords_list(page) + keyboard = get_refresh_kb(page) + + if is_callback: + await message.edit_text( + text=text, + parse_mode="HTML", + reply_markup=keyboard + ) + await update.answer("✅ Список обновлён") + else: + await message.answer( + text=text, + parse_mode="HTML", + reply_markup=keyboard + ) + + except Exception as e: + logger.error(f"Ошибка отправки списка банвордов: {e}", log_type="LISTWORDS") + + error_text = "❌ Ошибка загрузки списка\n\nПопробуйте позже" + + if is_callback: + await update.answer("❌ Ошибка загрузки", show_alert=True) + else: + await message.answer(error_text, parse_mode="HTML") 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) diff --git a/bot/handlers/commands/users/report.py b/bot/handlers/commands/users/report.py new file mode 100644 index 0000000..8ca7df4 --- /dev/null +++ b/bot/handlers/commands/users/report.py @@ -0,0 +1,447 @@ +""" +Обработчики команды /report для пользователей +""" +from datetime import datetime +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message, CallbackQuery, User +from aiogram.utils.keyboard import InlineKeyboardBuilder +from aiogram.exceptions import TelegramBadRequest + +from bot.filters.admin import IsAdmin +from configs import settings, COMMANDS +from database import get_manager +from middleware.loggers import logger + +__all__ = ("router",) + +router: Router = Router(name="report_router") + + +# ================= НАСТРОЙКИ ================= + +# ID чата для отправки репортов (можно вынести в configs) +# Если None, репорты отправляются всем владельцам в ЛС +REPORT_CHAT_ID = getattr(settings, 'REPORT_CHAT_ID', None) + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def format_user(user: User) -> str: + """ + Форматирует информацию о пользователе. + + Args: + user: Объект User + + Returns: + Отформатированная строка с именем и username + """ + if not user: + return "Unknown User" + + # Формируем имя + name_parts = [] + if user.first_name: + name_parts.append(user.first_name) + if user.last_name: + name_parts.append(user.last_name) + + full_name = " ".join(name_parts) if name_parts else "No Name" + + # Добавляем username если есть + if user.username: + return f"{full_name} (@{user.username})" + else: + return full_name + + +def format_datetime(dt: datetime) -> str: + """Форматирует datetime""" + return dt.strftime("%d.%m.%Y %H:%M:%S") + + +def truncate_text(text: str, max_length: int = 200) -> str: + """Обрезает текст до указанной длины""" + if len(text) <= max_length: + return text + return text[:max_length] + "..." + + +def get_report_keyboard( + chat_id: int, + message_id: int, + reported_user_id: int, + report_id: str +) -> InlineKeyboardBuilder: + """ + Создает клавиатуру для репорта. + + Args: + chat_id: ID чата, где было сообщение + message_id: ID сообщения + reported_user_id: ID пользователя, на которого пожаловались + report_id: Уникальный ID репорта + """ + ikb = InlineKeyboardBuilder() + + # Кнопки действий + ikb.button( + text="🚫 Забанить", + callback_data=f"report:ban:{chat_id}:{reported_user_id}:{report_id}" + ) + ikb.button( + text="🗑 Удалить", + callback_data=f"report:delete:{chat_id}:{message_id}:{report_id}" + ) + ikb.button( + text="✅ Закрыть", + callback_data=f"report:close:{report_id}" + ) + + ikb.adjust(2, 1) + return ikb + + +def generate_report_id() -> str: + """Генерирует уникальный ID репорта""" + return f"{int(datetime.now().timestamp() * 1000)}" + + +# ================= КОМАНДА РЕПОРТА ================= + +@router.message(Command(*COMMANDS.get("report", ["report"]), prefix=settings.PREFIX, ignore_case=True)) +async def report_cmd(message: Message) -> None: + """ + Отправляет жалобу на сообщение администраторам. + + Доступно всем пользователям. + + Использование: + /report — в ответ на сообщение + /report <причина> — в ответ на сообщение с указанием причины + + Пример: + /report спам + /report оскорбления + """ + # Проверяем, что команда в ответ на сообщение + if not message.reply_to_message: + await message.answer( + "❌ Используйте команду в ответ на сообщение\n\n" + "Как использовать:\n" + "1. Ответьте на сообщение нарушителя\n" + "2. Напишите /report или /report причина\n\n" + "Пример: /report спам", + parse_mode="HTML" + ) + return + + reported_message = message.reply_to_message + reported_user = reported_message.from_user + reporter = message.from_user + + # Проверка на None + if not reported_user or not reporter: + await message.answer("❌ Ошибка получения данных пользователя", parse_mode="HTML") + return + + # Нельзя пожаловаться на самого себя + if reported_user.id == reporter.id: + await message.answer( + "⚠️ Нельзя пожаловаться на самого себя", + parse_mode="HTML" + ) + return + + # Нельзя пожаловаться на бота + if reported_user.is_bot: + await message.answer( + "⚠️ Нельзя пожаловаться на бота", + parse_mode="HTML" + ) + return + + # Нельзя пожаловаться на администратора + manager = get_manager() + is_admin = await manager.is_admin(reported_user.id) or reported_user.id in settings.OWNER_ID + + if is_admin: + await message.answer( + "⚠️ Нельзя пожаловаться на администратора", + parse_mode="HTML" + ) + return + + # Извлекаем причину (опционально) + parts = message.text.split(maxsplit=1) + reason = parts[1] if len(parts) > 1 else "Не указана" + + # Генерируем ID репорта + report_id = generate_report_id() + + # === ФОРМИРУЕМ СООБЩЕНИЕ РЕПОРТА === + + report_text = "🚨 НОВЫЙ РЕПОРТ\n\n" + + # Информация о жалобщике + report_text += f"👤 От: {format_user(reporter)} ({reporter.id})\n" + + # Информация о нарушителе + report_text += f"⚠️ На: {format_user(reported_user)} ({reported_user.id})\n\n" + + # Информация о чате + chat_title = message.chat.title if message.chat.title else "Личные сообщения" + report_text += f"💬 Чат: {chat_title}\n" + report_text += f"🆔 Chat ID: {message.chat.id}\n\n" + + # Причина + report_text += f"📝 Причина: {reason}\n\n" + + # Текст сообщения + report_text += f"📄 Текст сообщения:\n" + + if reported_message.text: + truncated_text = truncate_text(reported_message.text, max_length=300) + report_text += f"{truncated_text}\n\n" + elif reported_message.caption: + truncated_caption = truncate_text(reported_message.caption, max_length=300) + report_text += f"{truncated_caption}\n\n" + else: + content_type = reported_message.content_type + report_text += f"[{content_type}]\n\n" + + # Время + report_text += f"🕐 Время: {format_datetime(datetime.now())}\n" + report_text += f"🔗 Message ID: {reported_message.message_id}\n\n" + + report_text += f"💡 ID репорта: {report_id}" + + # Клавиатура + keyboard = get_report_keyboard( + chat_id=message.chat.id, + message_id=reported_message.message_id, + reported_user_id=reported_user.id, + report_id=report_id + ) + + # === ОТПРАВКА РЕПОРТА === + + try: + # Если указан админ-чат, отправляем туда + if REPORT_CHAT_ID: + await message.bot.send_message( + chat_id=REPORT_CHAT_ID, + text=report_text, + parse_mode="HTML", + reply_markup=keyboard.as_markup() + ) + else: + # Отправляем всем владельцам + sent_count = 0 + for owner_id in settings.OWNER_ID: + try: + await message.bot.send_message( + chat_id=owner_id, + text=report_text, + parse_mode="HTML", + reply_markup=keyboard.as_markup() + ) + sent_count += 1 + except Exception as e: + logger.error(f"Ошибка отправки репорта владельцу {owner_id}: {e}", log_type="REPORT") + + if sent_count == 0: + raise Exception("Не удалось отправить репорт ни одному владельцу") + + # Подтверждение пользователю + await message.answer( + "✅ Жалоба отправлена администраторам\n\n" + "Спасибо за бдительность! Администраторы рассмотрят вашу жалобу.", + parse_mode="HTML" + ) + + # Логирование + logger.info( + f"Репорт #{report_id}: {reporter.id} → {reported_user.id} в чате {message.chat.id}", + log_type="REPORT" + ) + + except Exception as e: + logger.error(f"Ошибка отправки репорта: {e}", log_type="REPORT") + await message.answer( + "❌ Ошибка отправки жалобы\n\nПопробуйте позже или обратитесь к администратору напрямую.", + parse_mode="HTML" + ) + + +# ================= ОБРАБОТЧИКИ КНОПОК ================= + +@router.callback_query(F.data.startswith("report:ban:"), IsAdmin()) +async def report_ban_callback(callback: CallbackQuery) -> None: + """Обрабатывает нажатие кнопки 'Забанить'""" + try: + # Парсим данные: report:ban:chat_id:user_id:report_id + parts = callback.data.split(":") + chat_id = int(parts[2]) + user_id = int(parts[3]) + report_id = parts[4] + + # Баним пользователя + try: + await callback.bot.ban_chat_member( + chat_id=chat_id, + user_id=user_id + ) + + admin_name = format_user(callback.from_user) + + # Обновляем сообщение + updated_text = callback.message.text + f"\n\n✅ Пользователь забанен ({admin_name})" + + # Убираем кнопки + await callback.message.edit_text( + text=updated_text, + parse_mode="HTML" + ) + + await callback.answer("✅ Пользователь забанен", show_alert=True) + + logger.info( + f"Репорт #{report_id}: пользователь {user_id} забанен админом {callback.from_user.id}", + log_type="REPORT" + ) + + except TelegramBadRequest as e: + await callback.answer(f"❌ Ошибка бана: {str(e)}", show_alert=True) + + except Exception as e: + logger.error(f"Ошибка обработки бана из репорта: {e}", log_type="REPORT") + await callback.answer("❌ Ошибка выполнения", show_alert=True) + + +@router.callback_query(F.data.startswith("report:delete:"), IsAdmin()) +async def report_delete_callback(callback: CallbackQuery) -> None: + """Обрабатывает нажатие кнопки 'Удалить'""" + try: + # Парсим данные: report:delete:chat_id:message_id:report_id + parts = callback.data.split(":") + chat_id = int(parts[2]) + message_id = int(parts[3]) + report_id = parts[4] + + # Удаляем сообщение + try: + await callback.bot.delete_message( + chat_id=chat_id, + message_id=message_id + ) + + admin_name = format_user(callback.from_user) + + # Обновляем сообщение + updated_text = callback.message.text + f"\n\n🗑 Сообщение удалено ({admin_name})" + + # Убираем кнопки + await callback.message.edit_text( + text=updated_text, + parse_mode="HTML" + ) + + await callback.answer("✅ Сообщение удалено", show_alert=True) + + logger.info( + f"Репорт #{report_id}: сообщение {message_id} удалено админом {callback.from_user.id}", + log_type="REPORT" + ) + + except TelegramBadRequest as e: + await callback.answer(f"❌ Ошибка удаления: {str(e)}", show_alert=True) + + except Exception as e: + logger.error(f"Ошибка удаления из репорта: {e}", log_type="REPORT") + await callback.answer("❌ Ошибка выполнения", show_alert=True) + + +@router.callback_query(F.data.startswith("report:close:"), IsAdmin()) +async def report_close_callback(callback: CallbackQuery) -> None: + """Обрабатывает нажатие кнопки 'Закрыть'""" + try: + # Парсим данные: report:close:report_id + parts = callback.data.split(":") + report_id = parts[2] + + admin_name = format_user(callback.from_user) + + # Обновляем сообщение + updated_text = callback.message.text + f"\n\n✅ Репорт закрыт ({admin_name})" + + # Убираем кнопки + await callback.message.edit_text( + text=updated_text, + parse_mode="HTML" + ) + + await callback.answer("✅ Репорт закрыт") + + logger.info( + f"Репорт #{report_id} закрыт админом {callback.from_user.id}", + log_type="REPORT" + ) + + except Exception as e: + logger.error(f"Ошибка закрытия репорта: {e}", log_type="REPORT") + await callback.answer("❌ Ошибка выполнения", show_alert=True) + + +# ================= ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ ================= + +@router.message(Command(*COMMANDS.get("reporthelp", ["reporthelp"]), prefix=settings.PREFIX, ignore_case=True)) +async def report_help_cmd(message: Message) -> None: + """ + Показывает справку по системе репортов. + + Доступно всем пользователям. + """ + text = ( + "🚨 СИСТЕМА РЕПОРТОВ\n\n" + "Используйте команду /report, чтобы пожаловаться на сообщение администраторам.\n\n" + "📝 Как пожаловаться:\n" + "1. Ответьте на сообщение нарушителя\n" + "2. Напишите /report\n" + "3. Можно указать причину: /report спам\n\n" + "✅ Примеры:\n" + "• /report — жалоба без причины\n" + "• /report спам — жалоба на спам\n" + "• /report оскорбления — жалоба на оскорбления\n\n" + "⚠️ Важно:\n" + "├─ Нельзя пожаловаться на себя\n" + "├─ Нельзя пожаловаться на ботов\n" + "├─ Нельзя пожаловаться на администраторов\n" + "└─ Ложные жалобы могут привести к бану\n\n" + "💡 Администраторы получат уведомление и примут меры" + ) + + await message.answer(text, parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("reportstats", ["reportstats"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +async def report_stats_cmd(message: Message) -> None: + """ + Показывает статистику по репортам (для админов). + + TODO: Реализовать сохранение статистики в БД + """ + text = ( + "📊 СТАТИСТИКА РЕПОРТОВ\n\n" + "⚠️ Функция в разработке\n\n" + "Планируется:\n" + "• Всего репортов за всё время\n" + "• Топ жалобщиков\n" + "• Топ нарушителей\n" + "• Распределение по причинам\n" + "• Статистика обработки\n\n" + "💡 Для реализации нужно добавить таблицу reports в БД" + ) + + await message.answer(text, parse_mode="HTML") diff --git a/bot/handlers/commands/users/slience.py b/bot/handlers/commands/users/slience.py new file mode 100644 index 0000000..3f2b4b8 --- /dev/null +++ b/bot/handlers/commands/users/slience.py @@ -0,0 +1,346 @@ +""" +Обработчики команд режима тишины +""" +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 middleware.loggers import logger +from bot.utils.decorators import log_action + +__all__ = ("router",) + +router: Router = Router(name="silence_mode_router") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def parse_silence_args(text: str) -> tuple[bool, str | int]: + """ + Парсит аргументы команды для режима тишины. + + Args: + text: Полный текст сообщения + + Returns: + (success, result): result это либо минуты (int), либо текст ошибки (str) + """ + parts = text.split(maxsplit=1) + + if len(parts) < 2: + return False, "❌ Использование: /silence <минуты>" + + return True, parts[1] + + +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("silence", ["silence"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="START_SILENCE_MODE", log_args=True) +async def start_silence_mode_cmd(message: Message) -> None: + """ + Активирует режим тишины на указанное время. + + В этом режиме удаляются ВСЕ сообщения от обычных пользователей. + Администраторы могут продолжать писать. + + Использование: /silence <минуты> + Примеры: + /silence 30 — на 30 минут + /silence 120 — на 2 часа + /silence 1440 — на сутки + """ + success, result = parse_silence_args(message.text) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + # Валидация минут + try: + minutes = int(result) + 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: + # Проверяем, уже активен ли режим + is_already_active = await manager.is_silence_active() + + # Активируем режим (перезаписывает предыдущий, если был) + expires_at = await manager.set_silence_mode(minutes) + + time_str = format_time_str(minutes) + expires_str = format_datetime(expires_at) + + if is_already_active: + action_text = "🔄 РЕЖИМ ТИШИНЫ ОБНОВЛЁН" + else: + action_text = "🔇 РЕЖИМ ТИШИНЫ АКТИВИРОВАН" + + text = ( + f"{action_text}\n\n" + f"⏱ Длительность: {time_str}\n" + f"🕐 Окончание: {expires_str}\n\n" + f"⚠️ Что происходит:\n" + f"├─ Все сообщения от пользователей удаляются\n" + f"├─ Администраторы могут писать\n" + f"└─ Банворды временно отключены\n\n" + f"💡 Используйте для успокоения спора или флуда\n" + f"Отключить досрочно: /unsilence" + ) + + await message.answer(text, parse_mode="HTML") + + logger.info( + f"Режим тишины {'обновлён' if is_already_active else 'активирован'} на {minutes} мин " + f"пользователем {message.from_user.id}", + log_type="SILENCE" + ) + + except Exception as e: + logger.error(f"Ошибка активации режима тишины: {e}", log_type="SILENCE") + await message.answer("❌ Ошибка активации режима\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("unsilence", ["unsilence"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="STOP_SILENCE_MODE") +async def stop_silence_mode_cmd(message: Message) -> None: + """ + Отключает режим тишины. + + Использование: /unsilence + """ + manager = get_manager() + + try: + # Проверяем, активен ли режим + is_active = await manager.is_silence_active() + + if not is_active: + await message.answer( + "⚠️ Режим тишины не активен\n\n" + "Активируйте командой: /silence <минуты>", + parse_mode="HTML" + ) + return + + # Отключаем режим + await manager.disable_silence_mode() + + text = ( + f"✅ Режим тишины отключен\n\n" + f"🔊 Пользователи снова могут отправлять сообщения\n" + f"🔄 Банворды снова активны" + ) + + await message.answer(text, parse_mode="HTML") + + logger.info( + f"Режим тишины отключён пользователем {message.from_user.id}", + log_type="SILENCE" + ) + + except Exception as e: + logger.error(f"Ошибка отключения режима тишины: {e}", log_type="SILENCE") + await message.answer("❌ Ошибка отключения режима\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("silencestatus", ["silencestatus"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="SILENCE_STATUS") +async def silence_status_cmd(message: Message) -> None: + """ + Показывает статус режима тишины. + + Использование: /silencestatus + """ + manager = get_manager() + + try: + # Проверяем активность режима + is_active = await manager.is_silence_active() + + if is_active: + # Режим активен - показываем детали + silence_until_str = await manager.repo.get_setting("silence_until") + silence_until = float(silence_until_str) + expires_at = datetime.fromtimestamp(silence_until) + + now = datetime.now() + time_left_seconds = (expires_at - now).total_seconds() + time_left_minutes = int(time_left_seconds / 60) + + # Расчёт процента прошедшего времени (для визуализации) + # Примерно определяем начальное время + started_minutes_ago = 0 # Можно было бы сохранять в БД + + text = ( + f"🔇 РЕЖИМ ТИШИНЫ АКТИВЕН\n\n" + f"⏱ Осталось: {format_time_str(time_left_minutes)}\n" + f"🕐 Окончание: {format_datetime(expires_at)}\n\n" + f"⚠️ Что происходит:\n" + f"├─ Все сообщения от пользователей удаляются\n" + f"├─ Администраторы могут писать\n" + f"└─ Банворды временно отключены\n\n" + f"💡 Для успокоения конфликта или флуда\n" + f"Отключить: /unsilence" + ) + + # Добавляем визуальную шкалу прогресса + if time_left_minutes <= 60: + progress_bar = create_progress_bar(time_left_minutes, 60) + text += f"\n\n{progress_bar}" + + else: + # Режим не активен + text = ( + f"💤 Режим тишины НЕ активен\n\n" + f"🔊 Пользователи могут отправлять сообщения\n" + f"🔄 Банворды работают в обычном режиме\n\n" + f"Активировать: /silence <минуты>" + ) + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка получения статуса режима тишины: {e}", log_type="SILENCE") + await message.answer("❌ Ошибка получения статуса", parse_mode="HTML") + + +def create_progress_bar(minutes_left: int, total_minutes: int, length: int = 10) -> str: + """ + Создает визуальную шкалу прогресса. + + Args: + minutes_left: Сколько минут осталось + total_minutes: Всего минут + length: Длина шкалы + + Returns: + Строка с визуальной шкалой + """ + if total_minutes <= 0: + filled = 0 + else: + filled = int((total_minutes - minutes_left) / total_minutes * length) + + filled = max(0, min(filled, length)) + empty = length - filled + + bar = "█" * filled + "░" * empty + percentage = int((total_minutes - minutes_left) / total_minutes * 100) if total_minutes > 0 else 0 + + return f"[{bar}] {percentage}%" + + +@router.message(Command(*COMMANDS.get("extend_silence", ["extend_silence"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="EXTEND_SILENCE_MODE", log_args=True) +async def extend_silence_mode_cmd(message: Message) -> None: + """ + Продлевает режим тишины на указанное время. + + Использование: /extend_silence <минуты> + Пример: /extend_silence 30 + """ + success, result = parse_silence_args(message.text) + + if not success: + # Меняем текст ошибки для extend команды + await message.answer( + "❌ Использование: /extend_silence <минуты>", + parse_mode="HTML" + ) + return + + # Проверяем, активен ли режим + manager = get_manager() + is_active = await manager.is_silence_active() + + if not is_active: + await message.answer( + "⚠️ Режим тишины не активен\n\n" + "Сначала активируйте: /silence <минуты>", + parse_mode="HTML" + ) + return + + try: + add_minutes = int(result) + if add_minutes < 1 or add_minutes > 1440: + await message.answer( + "❌ Время продления должно быть от 1 до 1440 минут (24 часа)", + parse_mode="HTML" + ) + return + except ValueError: + await message.answer("❌ Неверный формат времени. Укажите число минут", parse_mode="HTML") + return + + try: + # Получаем текущее время окончания + silence_until_str = await manager.repo.get_setting("silence_until") + current_until = float(silence_until_str) + current_expires = datetime.fromtimestamp(current_until) + + # Вычисляем сколько минут осталось + добавляем новые + now = datetime.now() + current_minutes_left = int((current_expires - now).total_seconds() / 60) + new_total_minutes = current_minutes_left + add_minutes + + # Устанавливаем новое время + new_expires_at = await manager.set_silence_mode(new_total_minutes) + + time_str = format_time_str(add_minutes) + new_expires_str = format_datetime(new_expires_at) + + text = ( + f"⏱ РЕЖИМ ТИШИНЫ ПРОДЛЁН\n\n" + f"➕ Добавлено: {time_str}\n" + f"🕐 Новое окончание: {new_expires_str}\n" + f"⏳ Всего осталось: {format_time_str(new_total_minutes)}\n\n" + f"Отключить: /unsilence" + ) + + await message.answer(text, parse_mode="HTML") + + logger.info( + f"Режим тишины продлён на {add_minutes} мин (всего: {new_total_minutes} мин)", + log_type="SILENCE" + ) + + except Exception as e: + logger.error(f"Ошибка продления режима тишины: {e}", log_type="SILENCE") + await message.answer("❌ Ошибка продления режима\n\nПопробуйте позже", parse_mode="HTML") diff --git a/bot/handlers/commands/users/start_cmd.py b/bot/handlers/commands/users/start_cmd.py new file mode 100644 index 0000000..12cd9d0 --- /dev/null +++ b/bot/handlers/commands/users/start_cmd.py @@ -0,0 +1,168 @@ +""" +Обработчик команды /start и /help для администраторов. +Показывает список доступных команд для управления банвордами. +""" +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message, CallbackQuery +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from bot.filters.admin import IsAdmin +from configs import settings, COMMANDS +from middleware.loggers import logger +from bot.utils.decorators import log_action + +__all__ = ("router",) +CMD: str = "start" +router: Router = Router(name="start_cmd_router") + +def kb(text: str = "Создатель⬆️", url: str = "https://t.me/verdise"): + ikb = InlineKeyboardBuilder() + ikb.button(text=text, url=url) + return ikb.as_markup() + + +@router.callback_query(F.data.casefold() == CMD) +@router.message(Command(*COMMANDS[CMD], prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="START_COMMAND", log_args=True) +async def start_cmd(update: Message | CallbackQuery) -> None: + """ + Обработчик команды /start и /help. + Показывает справку по командам бота для администраторов. + + Доступно только администраторам (суперадмин или доп. админ из БД). + + Args: + update: Message или CallbackQuery + """ + print(123) + # Определяем тип update и извлекаем данные + if isinstance(update, CallbackQuery): + message = update.message + user_id = update.from_user.id + is_callback = True + else: + message = update + user_id = update.from_user.id + is_callback = False + + # Проверяем, является ли пользователь суперадмином + is_super_admin = user_id in settings.OWNER_ID + + # Формируем текст помощи + help_text = ( + "🤖 PrimoGuard - Бот-модератор\n\n" + "Автоматическое удаление сообщений с запрещёнными словами.\n" + "Поддержка подстрок, лемм, временных блокировок и режимов модерации.\n\n" + ) + + # === Команды просмотра === + help_text += ( + "📋 Просмотр:\n" + "/list — список всех правил и слов\n" + "/stats — статистика по удалениям\n" + "/id — получение айди пользователя\n" + "/chatid — получение айди чата\n\n" + ) + + # === Постоянные банворды === + help_text += ( + "➕ Добавить банворд (постоянно):\n" + "/addword слово — подстрока (простой поиск)\n" + "/addlemma слово — лемма (все формы слова)\n" + "/addpart комбинация — часть (поиск без пробелов)\n\n" + ) + + # === Временные банворды === + help_text += ( + "⏱ Добавить банворд (временно):\n" + "/addtempword слово минуты — временная подстрока\n" + "/addtemplemma слово минуты — временная лемма\n" + "Пример: /addtempword спам 60\n\n" + ) + + # === Исключения (whitelist) === + help_text += ( + "✅ Исключения (whitelist):\n" + "/addexcept текст — добавить исключение\n" + "/remexcept текст — удалить исключение\n" + "Исключения не проверяются фильтром\n\n" + ) + + # === Режимы модерации === + help_text += ( + "🔇 Режим тишины:\n" + "/silence минуты — удалять ВСЕ сообщения\n" + "/unsilence — отключить режим тишины\n\n" + ) + + help_text += ( + "⚔️ Режим антиконфликта:\n" + "/addconflictword слово — добавить конфликтное слово\n" + "/addconflictlemma слово — добавить конфликтную лемму\n" + "/stopconflict минуты — активировать режим\n" + "/unstopconflict — отключить режим\n\n" + ) + + # === Удаление === + help_text += ( + "➖ Удалить:\n" + "/remword слово — удалить подстроку\n" + "/remlemma слово — удалить лемму\n" + "/rempart комбинация — удалить часть\n" + "/remtempword слово — удалить временную подстроку\n" + "/remtemplemma слово — удалить временную лемму\n" + "/remconflictword слово — удалить конфликтное слово\n" + "/remconflictlemma слово — удалить конфликтную лемму\n\n" + ) + + # === Управление админами (только для суперадминов) === + if is_super_admin: + help_text += ( + "👑 Управление админами (только для владельцев):\n" + "/addadmin ID — добавить администратора\n" + "/remadmin ID — удалить администратора\n" + "/listadmins — список всех админов\n\n" + ) + + # === Типы проверок === + help_text += ( + "ℹ️ Типы проверок:\n" + "• Подстрока — простой поиск в тексте\n" + "• Лемма — все формы слова (купить→куплю, купил, купишь...)\n" + "• Часть — поиск без пробелов (обходит \"к у п и т ь\")\n" + "• Временные — автоматически удаляются через N минут\n" + "• Конфликтные — работают только в режиме /stopconflict\n\n" + ) + + help_text += ( + "🔧 Технологии:\n" + "• Unicode-нормализация (латиница→кириллица)\n" + "• Обход через разделители (\"с п а м\" → \"спам\")\n" + "• Морфологический анализ (pymorphy3)\n" + "• SQLAlchemy + SQLite с кэшированием\n\n" + "💾 Все настройки сохраняются в базе данных" + ) + + # Отправляем ответ + try: + if is_callback: + await message.edit_text( + text=help_text, + parse_mode="HTML", + reply_markup=kb() + ) + await update.answer() + else: + await message.answer( + text=help_text, + parse_mode="HTML", + reply_markup=kb() + ) + except Exception as e: + logger.error( + f"Ошибка отправки help сообщения: {e}", + log_type="ERROR" + ) + if is_callback: + await update.answer("❌ Ошибка отображения справки", show_alert=True) diff --git a/bot/handlers/commands/users/stats.py b/bot/handlers/commands/users/stats.py new file mode 100644 index 0000000..cef5ddf --- /dev/null +++ b/bot/handlers/commands/users/stats.py @@ -0,0 +1,589 @@ +""" +Обработчики команды статистики +""" +from datetime import datetime +from aiogram import Router, F +from aiogram.filters import Command +from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from bot.filters.admin import IsAdmin +from configs import settings, COMMANDS +from database import get_manager +from middleware.loggers import logger +from bot.utils.decorators import log_action + +__all__ = ("router",) + +router: Router = Router(name="stats_router") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def format_number(num: int) -> str: + """Форматирует большие числа с разделителями""" + return f"{num:,}".replace(",", " ") + + +def create_text_bar(value: int, max_value: int, length: int = 10) -> str: + """Создает текстовую полоску прогресса""" + if max_value == 0: + return "░" * length + + filled = int((value / max_value) * length) + filled = max(0, min(filled, length)) + empty = length - filled + + return "█" * filled + "░" * empty + + +def format_datetime(dt: datetime) -> str: + """Форматирует datetime в читабельный формат""" + return dt.strftime("%d.%m.%Y %H:%M") + + +def format_time_remaining(minutes: int) -> str: + """ + Форматирует оставшееся время в читабельный формат. + + Args: + minutes: Количество минут + + Returns: + Отформатированная строка времени + """ + if minutes <= 0: + return "истёк" + elif minutes < 60: + return f"{minutes} мин" + elif minutes < 1440: # < 24 часов + hours = minutes // 60 + mins = minutes % 60 + if mins > 0: + return f"{hours}ч {mins}м" + return f"{hours}ч" + else: # >= 24 часов + days = minutes // 1440 + hours = (minutes % 1440) // 60 + if hours > 0: + return f"{days}д {hours}ч" + return f"{days}д" + + +def get_stats_keyboard(): + """Клавиатура для статистики""" + ikb = InlineKeyboardBuilder() + ikb.button(text="🔄 Обновить", callback_data="stats:refresh") + ikb.button(text="📊 Детали", callback_data="stats:details") + ikb.button(text="🏆 Топ-спамеры", callback_data="stats:top_spammers") + ikb.button(text="🔤 Топ-слова", callback_data="stats:top_words") + ikb.button(text="🚀 Назад", callback_data="start") + ikb.adjust(2, 2, 1) + return ikb.as_markup() + + +# ================= ОСНОВНАЯ СТАТИСТИКА ================= + +@router.callback_query(F.data == "stats:refresh") +@router.callback_query(F.data == "stats") +@router.message(Command(*COMMANDS.get("stats", ["stats"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="VIEW_STATS") +async def stats_cmd(update: Message | CallbackQuery) -> None: + """ + Показывает общую статистику работы бота. + + Включает: + - Общее количество удалений + - Активные режимы + - Статистику банвордов + - Топ спамеров + + Использование: /stats + """ + # Определяем тип update + if isinstance(update, CallbackQuery): + message = update.message + is_callback = True + else: + message = update + is_callback = False + + manager = get_manager() + + try: + # Получаем данные + stats = await manager.get_stats() + data = await manager.get_all_words_list() + top_spammers = await manager.get_top_spammers(limit=5) + + # Проверяем активные режимы + is_silence = await manager.is_silence_active() + is_conflict = await manager.is_conflict_active() + + # === ФОРМИРУЕМ ВЫВОД === + + output = "📊 СТАТИСТИКА PRIMOGUARD\n\n" + + # Общая информация + total_deletions = stats.get('total_deletions', 0) + output += f"🗑 Всего удалений: {format_number(total_deletions)}\n\n" + + # Активные режимы + if is_silence or is_conflict: + output += "🔴 АКТИВНЫЕ РЕЖИМЫ:\n\n" + + if is_silence: + silence_until_str = await manager.repo.get_setting("silence_until") + silence_until = datetime.fromtimestamp(float(silence_until_str)) + time_left_seconds = (silence_until - datetime.now()).total_seconds() + time_left_minutes = int(time_left_seconds / 60) + + output += f"🔇 Режим тишины\n" + output += f"├─ ⏱ Осталось: {format_time_remaining(time_left_minutes)}\n" + output += f"└─ 🕐 До: {format_datetime(silence_until)}\n" + + if is_conflict: + output += "│\n" + + if is_conflict: + conflict_until_str = await manager.repo.get_setting("conflict_until") + conflict_until = datetime.fromtimestamp(float(conflict_until_str)) + time_left_seconds = (conflict_until - datetime.now()).total_seconds() + time_left_minutes = int(time_left_seconds / 60) + + 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 + + output += f"⚔️ Режим антиконфликта\n" + output += f"├─ ⏱ Осталось: {format_time_remaining(time_left_minutes)}\n" + output += f"├─ 🕐 До: {format_datetime(conflict_until)}\n" + output += f"└─ 📊 Правил: {total_conflict}\n" + + output += "\n" + + # Статистика правил + total_rules = ( + len(data.get('substring', set())) + + len(data.get('lemma', set())) + + len(data.get('part', set())) + + len(data.get('temp_substring', set())) + + len(data.get('temp_lemma', set())) + + len(data.get('conflict_substring', set())) + + len(data.get('conflict_lemma', set())) + ) + + output += f"📋 Правила модерации:\n" + output += f"├─ Всего правил: {total_rules}\n" + output += f"├─ Постоянные: {len(data.get('substring', set())) + len(data.get('lemma', set())) + len(data.get('part', set()))}\n" + output += f"├─ Временные: {len(data.get('temp_substring', set())) + len(data.get('temp_lemma', set()))}\n" + output += f"├─ Конфликтные: {len(data.get('conflict_substring', set())) + len(data.get('conflict_lemma', set()))}\n" + output += f"└─ Исключения: {len(data.get('whitelist', set()))}\n\n" + + # Топ-5 спамеров + if top_spammers: + output += "🏆 Топ-5 спамеров:\n" + max_count = top_spammers[0][1] if top_spammers else 1 + + for idx, (user_id, count) in enumerate(top_spammers, 1): + bar = create_text_bar(count, max_count, length=8) + output += f"{idx}. {user_id} — {count} [{bar}]\n" + + output += "\n" + else: + output += "🏆 Топ-5 спамеров:\n" + output += "└─ Нет данных\n\n" + + # Администраторы + admins_count = len(settings.OWNER_ID) + len(data.get('admins', set())) + output += f"👥 Администраторов: {admins_count}\n\n" + + # Подсказка + output += "💡 Используйте кнопки для детальной информации" + + # Клавиатура + keyboard = get_stats_keyboard() + + # Отправка + if is_callback: + await message.edit_text( + text=output, + parse_mode="HTML", + reply_markup=keyboard + ) + await update.answer("✅ Статистика обновлена") + else: + await message.answer( + text=output, + parse_mode="HTML", + reply_markup=keyboard + ) + + except Exception as e: + logger.error(f"Ошибка получения статистики: {e}", log_type="STATS") + + error_text = "❌ Ошибка загрузки статистики\n\nПопробуйте позже" + + if is_callback: + await update.answer("❌ Ошибка загрузки", show_alert=True) + else: + await message.answer(error_text, parse_mode="HTML") + + +# ================= ДЕТАЛЬНАЯ СТАТИСТИКА ================= + +@router.callback_query(F.data == "stats:details") +@log_action(action_name="VIEW_DETAILED_STATS") +async def stats_details_callback(callback: CallbackQuery) -> None: + """Показывает детальную статистику""" + manager = get_manager() + + try: + stats = await manager.get_stats() + data = await manager.get_all_words_list() + + output = "📊 ДЕТАЛЬНАЯ СТАТИСТИКА\n\n" + + # Подробная статистика удалений + total_deletions = stats.get('total_deletions', 0) + output += f"🗑 Удаления сообщений:\n" + output += f"├─ Всего: {format_number(total_deletions)}\n" + output += "\n" + + # Активные режимы (детально) + is_silence = await manager.is_silence_active() + is_conflict = await manager.is_conflict_active() + + if is_silence or is_conflict: + output += "🔴 Активные режимы:\n\n" + + if is_silence: + silence_until_str = await manager.repo.get_setting("silence_until") + silence_until = datetime.fromtimestamp(float(silence_until_str)) + time_left_seconds = (silence_until - datetime.now()).total_seconds() + time_left_minutes = int(time_left_seconds / 60) + + output += f"🔇 Режим тишины:\n" + output += f"├─ Статус: ✅ Активен\n" + output += f"├─ Осталось: {format_time_remaining(time_left_minutes)}\n" + output += f"├─ Окончание: {format_datetime(silence_until)}\n" + output += f"└─ Эффект: Удаляются ВСЕ сообщения\n\n" + + if is_conflict: + conflict_until_str = await manager.repo.get_setting("conflict_until") + conflict_until = datetime.fromtimestamp(float(conflict_until_str)) + time_left_seconds = (conflict_until - datetime.now()).total_seconds() + time_left_minutes = int(time_left_seconds / 60) + + conflict_words_count = len(data.get('conflict_substring', set())) + conflict_lemmas_count = len(data.get('conflict_lemma', set())) + + output += f"⚔️ Режим антиконфликта:\n" + output += f"├─ Статус: ✅ Активен\n" + output += f"├─ Осталось: {format_time_remaining(time_left_minutes)}\n" + output += f"├─ Окончание: {format_datetime(conflict_until)}\n" + output += f"├─ Слов: {conflict_words_count}\n" + output += f"├─ Лемм: {conflict_lemmas_count}\n" + output += f"└─ Эффект: Обычные банворды отключены\n\n" + + # Детальная статистика правил + output += f"📋 Правила модерации:\n\n" + + output += f"🔴 Постоянные:\n" + output += f"├─ Подстроки: {len(data.get('substring', set()))}\n" + output += f"├─ Леммы: {len(data.get('lemma', set()))}\n" + output += f"└─ Части: {len(data.get('part', set()))}\n\n" + + output += f"⏱ Временные:\n" + output += f"├─ Подстроки: {len(data.get('temp_substring', set()))}\n" + output += f"└─ Леммы: {len(data.get('temp_lemma', set()))}\n\n" + + output += f"⚔️ Конфликтные:\n" + output += f"├─ Слова: {len(data.get('conflict_substring', set()))}\n" + output += f"└─ Леммы: {len(data.get('conflict_lemma', set()))}\n\n" + + output += f"✅ Исключения: {len(data.get('whitelist', set()))}\n\n" + + # Информация о кэше + cache_info = stats.get('cache_active', False) + cache_updated = stats.get('cache_updated_at', None) + + output += f"💾 Кэш:\n" + output += f"├─ Статус: {'✅ Активен' if cache_info else '❌ Неактивен'}\n" + + if cache_updated and isinstance(cache_updated, str): + try: + updated_dt = datetime.fromisoformat(cache_updated) + output += f"└─ Обновлён: {format_datetime(updated_dt)}\n" + except (ValueError, TypeError): + output += f"└─ Обновлён: недавно\n" + else: + output += f"└─ Не обновлялся\n" + + # Кнопка возврата + ikb = InlineKeyboardBuilder() + ikb.button(text="◀️ Назад", callback_data="stats:refresh") + + await callback.message.edit_text( + text=output, + parse_mode="HTML", + reply_markup=ikb.as_markup() + ) + await callback.answer() + + except Exception as e: + logger.error(f"Ошибка получения детальной статистики: {e}", log_type="STATS") + await callback.answer("❌ Ошибка загрузки", show_alert=True) + + +# ================= ТОП СПАМЕРОВ ================= + +@router.callback_query(F.data == "stats:top_spammers") +@log_action(action_name="VIEW_TOP_SPAMMERS") +async def stats_top_spammers_callback(callback: CallbackQuery) -> None: + """Показывает топ-10 спамеров""" + manager = get_manager() + + try: + top_spammers = await manager.get_top_spammers(limit=10) + + output = "🏆 ТОП-10 СПАМЕРОВ\n\n" + + if top_spammers: + max_count = top_spammers[0][1] if top_spammers else 1 + + for idx, (user_id, count) in enumerate(top_spammers, 1): + bar = create_text_bar(count, max_count, length=10) + + # Эмодзи для топ-3 + if idx == 1: + medal = "🥇" + elif idx == 2: + medal = "🥈" + elif idx == 3: + medal = "🥉" + else: + medal = f"{idx}." + + output += f"{medal} {user_id}\n" + output += f" └─ {format_number(count)} удалений [{bar}]\n\n" + + # Общая статистика + total_spammers = len(top_spammers) + total_deletions = sum(count for _, count in top_spammers) + + output += f"📊 Статистика:\n" + output += f"├─ Всего пользователей: {total_spammers}\n" + output += f"└─ Всего удалений: {format_number(total_deletions)}\n\n" + + output += "💡 ID можно использовать для проверки пользователя" + else: + output += "└─ Нет данных об удалениях\n\n" + output += "💡 Когда бот начнёт удалять сообщения, здесь появится статистика" + + # Кнопка возврата + ikb = InlineKeyboardBuilder() + ikb.button(text="◀️ Назад", callback_data="stats:refresh") + + await callback.message.edit_text( + text=output, + parse_mode="HTML", + reply_markup=ikb.as_markup() + ) + await callback.answer() + + except Exception as e: + logger.error(f"Ошибка получения топ спамеров: {e}", log_type="STATS") + await callback.answer("❌ Ошибка загрузки", show_alert=True) + + +# ================= ТОП СЛОВ ================= + +@router.callback_query(F.data == "stats_top_words") +async def stats_top_words_callback(callback: CallbackQuery) -> None: + """Показывает топ-10 самых частых срабатываний""" + await callback.answer() + + manager = get_manager() + + # Получаем топ слов + top_words = await manager.get_top_words(limit=10) + + if not top_words: + text = ( + "🔤 ТОП-10 СРАБАТЫВАНИЙ ПО СЛОВАМ\n\n" + "📭 Статистика пока пуста\n\n" + "Срабатывания появятся после удаления\n" + "первых спам-сообщений." + ) + else: + text = "🔤 ТОП-10 СРАБАТЫВАНИЙ ПО СЛОВАМ\n\n" + + # Эмодзи для типов + type_emoji = { + "substring": "🔤", + "lemma": "📖", + "part": "🧩", + "silence": "🔇", + "conflict_substring": "⚔️", + "conflict_lemma": "⚔️" + } + + for i, word_data in enumerate(top_words, 1): + word = word_data['word'] + count = word_data['count'] + word_type = word_data['type'] + emoji = type_emoji.get(word_type, "❓") + + # Медали для топ-3 + medal = "" + if i == 1: + medal = "🥇 " + elif i == 2: + medal = "🥈 " + elif i == 3: + medal = "🥉 " + + text += f"{medal}{i}. {emoji} {word} — {count} раз\n" + + # Общая статистика + total = await manager.get_total_spam_count() + text += f"\n📊 Всего удалено: {total} сообщений" + + # Кнопка назад + keyboard = InlineKeyboardMarkup(inline_keyboard=[ + [InlineKeyboardButton(text="◀️ Назад", callback_data="show_stats")] + ]) + + try: + await callback.message.edit_text( + text=text, + reply_markup=keyboard, + parse_mode="HTML" + ) + except Exception as e: + logger.error(f"Ошибка показа топ-слов: {e}", log_type="ERROR") + await callback.answer("❌ Ошибка загрузки статистики", show_alert=True) + + +# ================= СТАТИСТИКА ПОЛЬЗОВАТЕЛЯ ================= + +@router.message(Command(*COMMANDS.get("userstats", ["userstats"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="VIEW_USER_STATS", log_args=True) +async def user_stats_cmd(message: Message) -> None: + """ + Показывает статистику конкретного пользователя. + + Использование: /userstats + Пример: /userstats 123456789 + """ + parts = message.text.split(maxsplit=1) + + if len(parts) < 2: + await message.answer( + "❌ Использование: /userstats [ID]\n\n" + "Пример: /userstats 123456789", + parse_mode="HTML" + ) + return + + try: + user_id = int(parts[1].strip()) + except ValueError: + await message.answer("❌ ID должен быть числом", parse_mode="HTML") + return + + manager = get_manager() + + try: + # Получаем статистику пользователя + user_spam_count = await manager.get_user_spam_count(user_id) + user_spam_stats = await manager.get_spam_stats(limit=10, user_id=user_id) + + output = f"👤 СТАТИСТИКА ПОЛЬЗОВАТЕЛЯ\n\n" + output += f"🆔 ID: {user_id}\n\n" + + if user_spam_count > 0: + output += f"🗑 Удалено сообщений: {format_number(user_spam_count)}\n\n" + + if user_spam_stats: + output += f"📝 Последние удаления:\n" + + for stat in user_spam_stats[:5]: + deleted_at = stat.deleted_at + matched_word = stat.matched_word or "неизвестно" + match_type = stat.match_type or "unknown" + + output += f"├─ {format_datetime(deleted_at)}\n" + output += f"│ └─ Слово: {matched_word} ({match_type})\n" + + output += "\n" + else: + output += "✅ Нет нарушений\n\n" + output += "Этот пользователь не нарушал правила чата" + + await message.answer(output, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка получения статистики пользователя: {e}", log_type="STATS") + await message.answer("❌ Ошибка загрузки статистики", parse_mode="HTML") + + +# ================= СБРОС СТАТИСТИКИ ================= + +@router.message(Command(*COMMANDS.get("resetstats", ["resetstats"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="RESET_STATS") +async def reset_stats_cmd(message: Message) -> None: + """ + Сбрасывает всю статистику удалений. + + ⚠️ ВНИМАНИЕ: Это действие необратимо! + + Использование: /resetstats confirm + """ + parts = message.text.split(maxsplit=1) + + if len(parts) < 2 or parts[1].lower() != "confirm": + await message.answer( + "⚠️ ВНИМАНИЕ!\n\n" + "Эта команда удалит ВСЮ статистику удалений:\n" + "• Счётчики удалений пользователей\n" + "• Историю удалённых сообщений\n" + "• Топ спамеров\n\n" + "Правила модерации НЕ будут удалены.\n\n" + "Для подтверждения используйте:\n" + "/resetstats confirm", + parse_mode="HTML" + ) + return + + manager = get_manager() + + try: + # Сбрасываем статистику + deleted_count = await manager.reset_spam_stats() + + if deleted_count > 0: + await message.answer( + f"✅ Статистика сброшена\n\n" + f"Удалено записей: {deleted_count}\n\n" + f"Новые данные начнут собираться\n" + f"с этого момента.", + parse_mode="HTML" + ) + logger.warning( + f"Статистика сброшена пользователем {message.from_user.id}: " + f"удалено {deleted_count} записей", + log_type="STATS" + ) + else: + await message.answer( + "ℹ️ Статистика уже пуста", + parse_mode="HTML" + ) + + except Exception as e: + logger.error(f"Ошибка сброса статистики: {e}", log_type="STATS") + await message.answer("❌ Ошибка сброса статистики", parse_mode="HTML") + diff --git a/bot/handlers/commands/users/word.py b/bot/handlers/commands/users/word.py new file mode 100644 index 0000000..78083ae --- /dev/null +++ b/bot/handlers/commands/users/word.py @@ -0,0 +1,546 @@ +""" +Обработчики команд добавления и удаления банвордов +""" +from aiogram import Router, F +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="manage_words_router") + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def parse_args(text: str, command: str, min_args: int = 1, max_args: int = 2) -> tuple[bool, str | list]: + """ + Парсит аргументы команды. + + Args: + text: Полный текст сообщения + command: Название команды + min_args: Минимальное количество аргументов + max_args: Максимальное количество аргументов + + Returns: + (success, result): result это либо список аргументов, либо текст ошибки + """ + # Убираем команду из текста + parts = text.split(maxsplit=max_args) + + if len(parts) < min_args + 1: + return False, f"❌ Использование: /{command} {'<слово>' if min_args == 1 else '<слово> <минуты>'}" + + args = parts[1:] + + # Валидация длины слова + if args and len(args[0]) < 2: + return False, "❌ Слово должно содержать минимум 2 символа" + + if args and len(args[0]) > 100: + return False, "❌ Слово слишком длинное (максимум 100 символов)" + + return True, args + + +def format_success_message(action: str, word: str, word_type: str, extra: str = "") -> str: + """Форматирует сообщение об успехе""" + emoji_map = { + 'добавлена': '✅', + 'добавлен': '✅', + 'добавлено': '✅', + 'удалена': '🗑', + 'удален': '🗑', + 'удалено': '🗑' + } + + emoji = emoji_map.get(action, '✅') + + message = f"{emoji} {word_type.capitalize()} {word} {action}" + + if extra: + message += f"\n{extra}" + + return message + + +# ================= КОМАНДЫ ДОБАВЛЕНИЯ ================= + +@router.message(Command(*COMMANDS.get("addword", ["addword"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="ADD_WORD", log_args=True) +async def add_word_cmd(message: Message) -> None: + """ + Добавляет банворд-подстроку (постоянно). + + Использование: /addword <слово> + """ + success, result = parse_args(message.text, "addword", min_args=1, max_args=1) + + 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.SUBSTRING, + added_by=message.from_user.id, + reason=f"Добавлено через команду" + ) + + if added: + text = format_success_message( + "добавлена", + word, + "подстрока", + "🔍 Тип проверки: простой поиск в тексте" + ) + else: + text = f"⚠️ Подстрока {word} уже существует" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления банворда: {e}", log_type="CMD") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("addlemma", ["addlemma"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="ADD_LEMMA", log_args=True) +async def add_lemma_cmd(message: Message) -> None: + """ + Добавляет банворд-лемму (постоянно). + + Использование: /addlemma <слово> + """ + success, result = parse_args(message.text, "addlemma", min_args=1, max_args=1) + + 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.LEMMA, + added_by=message.from_user.id, + reason=f"Добавлено через команду" + ) + + if added: + text = format_success_message( + "добавлена", + word, + "лемма", + "🔤 Тип проверки: все формы слова (купить→куплю, купил, купишь...)" + ) + else: + text = f"⚠️ Лемма {word} уже существует" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления леммы: {e}", log_type="CMD") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("addpart", ["addpart"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="ADD_PART", log_args=True) +async def add_part_cmd(message: Message) -> None: + """ + Добавляет банворд-часть (постоянно). + + Использование: /addpart <комбинация> + """ + success, result = parse_args(message.text, "addpart", min_args=1, max_args=1) + + 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.PART, + added_by=message.from_user.id, + reason=f"Добавлено через команду" + ) + + if added: + text = format_success_message( + "добавлена", + word, + "часть", + "🧩 Тип проверки: поиск без пробелов (обходит \"к у п и т ь\")" + ) + else: + text = f"⚠️ Часть {word} уже существует" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления части: {e}", log_type="CMD") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("addtempword", ["addtempword"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="ADD_TEMP_WORD", log_args=True) +async def add_temp_word_cmd(message: Message) -> None: + """ + Добавляет временную банворд-подстроку. + + Использование: /addtempword <слово> <минуты> + """ + success, result = parse_args(message.text, "addtempword", min_args=2, max_args=2) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + word = result[0].lower().strip() + + # Валидация минут + try: + minutes = int(result[1]) + 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: + added = await manager.add_temp_banword( + word=word, + word_type=BanWordType.SUBSTRING, + minutes=minutes, + added_by=message.from_user.id + ) + + if added: + # Форматируем время + if minutes < 60: + time_str = f"{minutes} мин" + elif minutes < 1440: + hours = minutes // 60 + mins = minutes % 60 + time_str = f"{hours}ч {mins}м" if mins else f"{hours}ч" + else: + days = minutes // 1440 + hours = (minutes % 1440) // 60 + time_str = f"{days}д {hours}ч" if hours else f"{days}д" + + text = format_success_message( + "добавлена", + word, + "временная подстрока", + f"⏱ Автоматически удалится через {time_str}" + ) + else: + text = f"⚠️ Временная подстрока {word} уже существует" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления временного банворда: {e}", log_type="CMD") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("addtemplemma", ["addtemplemma"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="ADD_TEMP_LEMMA", log_args=True) +async def add_temp_lemma_cmd(message: Message) -> None: + """ + Добавляет временную банворд-лемму. + + Использование: /addtemplemma <слово> <минуты> + """ + success, result = parse_args(message.text, "addtemplemma", min_args=2, max_args=2) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + word = result[0].lower().strip() + + try: + minutes = int(result[1]) + 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: + added = await manager.add_temp_banword( + word=word, + word_type=BanWordType.LEMMA, + minutes=minutes, + added_by=message.from_user.id + ) + + if added: + if minutes < 60: + time_str = f"{minutes} мин" + elif minutes < 1440: + hours = minutes // 60 + mins = minutes % 60 + time_str = f"{hours}ч {mins}м" if mins else f"{hours}ч" + else: + days = minutes // 1440 + hours = (minutes % 1440) // 60 + time_str = f"{days}д {hours}ч" if hours else f"{days}д" + + text = format_success_message( + "добавлена", + word, + "временная лемма", + f"⏱ Автоматически удалится через {time_str}" + ) + else: + text = f"⚠️ Временная лемма {word} уже существует" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления временной леммы: {e}", log_type="CMD") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("addexcept", ["addexcept"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="ADD_EXCEPTION", log_args=True) +async def add_exception_cmd(message: Message) -> None: + """ + Добавляет исключение в whitelist. + + Использование: /addexcept <текст> + """ + success, result = parse_args(message.text, "addexcept", min_args=1, max_args=1) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + word = result[0].lower().strip() + manager = get_manager() + + try: + added = await manager.add_whitelist( + word=word, + added_by=message.from_user.id, + reason="Добавлено через команду" + ) + + if added: + text = format_success_message( + "добавлено", + word, + "исключение", + "✅ Сообщения с этим текстом не будут проверяться" + ) + else: + text = f"⚠️ Исключение {word} уже существует" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка добавления исключения: {e}", log_type="CMD") + await message.answer("❌ Ошибка добавления\n\nПопробуйте позже", parse_mode="HTML") + + +# ================= КОМАНДЫ УДАЛЕНИЯ ================= + +@router.message(Command(*COMMANDS.get("remword", ["remword"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="REMOVE_WORD", log_args=True) +async def remove_word_cmd(message: Message) -> None: + """ + Удаляет банворд-подстроку. + + Использование: /remword <слово> + """ + success, result = parse_args(message.text, "remword", min_args=1, max_args=1) + + 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.SUBSTRING) + + if removed: + text = format_success_message("удалена", word, "подстрока") + else: + text = f"⚠️ Подстрока {word} не найдена" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления банворда: {e}", log_type="CMD") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("remlemma", ["remlemma"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="REMOVE_LEMMA", log_args=True) +async def remove_lemma_cmd(message: Message) -> None: + """Удаляет банворд-лемму""" + success, result = parse_args(message.text, "remlemma", min_args=1, max_args=1) + + 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.LEMMA) + + if removed: + text = format_success_message("удалена", word, "лемма") + else: + text = f"⚠️ Лемма {word} не найдена" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления леммы: {e}", log_type="CMD") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("rempart", ["rempart"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="REMOVE_PART", log_args=True) +async def remove_part_cmd(message: Message) -> None: + """Удаляет банворд-часть""" + success, result = parse_args(message.text, "rempart", min_args=1, max_args=1) + + 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.PART) + + if removed: + text = format_success_message("удалена", word, "часть") + else: + text = f"⚠️ Часть {word} не найдена" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления части: {e}", log_type="CMD") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("remtempword", ["remtempword"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="REMOVE_TEMP_WORD", log_args=True) +async def remove_temp_word_cmd(message: Message) -> None: + """Удаляет временную подстроку""" + success, result = parse_args(message.text, "remtempword", min_args=1, max_args=1) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + word = result[0].lower().strip() + manager = get_manager() + + try: + removed = await manager.remove_temp_banword(word=word, word_type=BanWordType.SUBSTRING) + + if removed: + text = format_success_message("удалена", word, "временная подстрока") + else: + text = f"⚠️ Временная подстрока {word} не найдена" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления временного банворда: {e}", log_type="CMD") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("remtemplemma", ["remtemplemma"]), prefix=settings.PREFIX, ignore_case=True), + IsAdmin()) +@log_action(action_name="REMOVE_TEMP_LEMMA", log_args=True) +async def remove_temp_lemma_cmd(message: Message) -> None: + """Удаляет временную лемму""" + success, result = parse_args(message.text, "remtemplemma", min_args=1, max_args=1) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + word = result[0].lower().strip() + manager = get_manager() + + try: + removed = await manager.remove_temp_banword(word=word, word_type=BanWordType.LEMMA) + + if removed: + text = format_success_message("удалена", word, "временная лемма") + else: + text = f"⚠️ Временная лемма {word} не найдена" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления временной леммы: {e}", log_type="CMD") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") + + +@router.message(Command(*COMMANDS.get("remexcept", ["remexcept"]), prefix=settings.PREFIX, ignore_case=True), IsAdmin()) +@log_action(action_name="REMOVE_EXCEPTION", log_args=True) +async def remove_exception_cmd(message: Message) -> None: + """Удаляет исключение из whitelist""" + success, result = parse_args(message.text, "remexcept", min_args=1, max_args=1) + + if not success: + await message.answer(result, parse_mode="HTML") + return + + word = result[0].lower().strip() + manager = get_manager() + + try: + removed = await manager.remove_whitelist(word=word) + + if removed: + text = format_success_message("удалено", word, "исключение") + else: + text = f"⚠️ Исключение {word} не найдено" + + await message.answer(text, parse_mode="HTML") + + except Exception as e: + logger.error(f"Ошибка удаления исключения: {e}", log_type="CMD") + await message.answer("❌ Ошибка удаления\n\nПопробуйте позже", parse_mode="HTML") diff --git a/bot/handlers/messages/__init__.py b/bot/handlers/messages/__init__.py new file mode 100644 index 0000000..9efe58a --- /dev/null +++ b/bot/handlers/messages/__init__.py @@ -0,0 +1,15 @@ +from aiogram import Router + +from .default_msg import router as default_message_router +from .ping_test import router as ping_test_message_router + +# Настройка экспорта и роутера +router: Router = Router(name=__name__) + +# Подготовка роутера команд +# router.include_routers( +# ping_test_message_router, +# ) + +# Подключение стандартного роутера +router.include_router(default_message_router) diff --git a/bot/handlers/messages/default_msg.py b/bot/handlers/messages/default_msg.py new file mode 100644 index 0000000..517c143 --- /dev/null +++ b/bot/handlers/messages/default_msg.py @@ -0,0 +1,11 @@ +from aiogram import Router +from aiogram.types import Message + +# Настройки экспорта и роутера +router: Router = Router(name=__name__) + + +@router.message() +async def default_msg(message: Message) -> None: + """Обработчик всех необработанных сообщений.""" + return diff --git a/bot/handlers/messages/ping_test.py b/bot/handlers/messages/ping_test.py new file mode 100644 index 0000000..8e2bf2a --- /dev/null +++ b/bot/handlers/messages/ping_test.py @@ -0,0 +1,32 @@ +from aiogram import Router +from aiogram.types import Message + +router: Router = Router(name=__name__) + +# Словарь с ответами по ключам +RESPONSE_DICT: dict[str, str] = { + "пинг": "Понг! 🏓", + "понг": "Пинг!", + "бот": "На месте! 🤖", +} + + +@router.message() +async def auto_response_handler(message: Message) -> None: + """Обработчик автоматических ответов по ключевым словам.""" + if not message.text: + return + + text_lower: str = message.text.casefold().strip() + + # Поиск точного совпадения + if text_lower in RESPONSE_DICT: + response: str = RESPONSE_DICT[text_lower] + await message.answer(response) + return + + # Поиск частичного совпадения (если хотите расширенную функциональность) + for key, response in RESPONSE_DICT.items(): + if key in text_lower and len(key) > 3: # Только для ключей длиннее 3 символов + await message.answer(response) + return diff --git a/bot/keyboards/__init__.py b/bot/keyboards/__init__.py new file mode 100644 index 0000000..93f594b --- /dev/null +++ b/bot/keyboards/__init__.py @@ -0,0 +1,2 @@ +from .inline import * +from .reply import * diff --git a/bot/keyboards/inline.py b/bot/keyboards/inline.py new file mode 100644 index 0000000..05d39bd --- /dev/null +++ b/bot/keyboards/inline.py @@ -0,0 +1,17 @@ +from aiogram.utils.keyboard import InlineKeyboardBuilder +from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton + +def decision_keyboard(thread_id: int, kind: str) -> InlineKeyboardMarkup: + """ + Получение клавиатуры Принятия\Отклонить. + + :param thread_id: Айди действия. + :param kind: Вид для клавиатуры. + :return: Инлайн-клавиатуру (Принять, Отклонить). + """ + ikb: InlineKeyboardBuilder = InlineKeyboardBuilder() + ikb.row( + InlineKeyboardButton(text="✅ Принять", callback_data=f"{kind}:accept:{thread_id}"), + InlineKeyboardButton(text="❌ Отклонить", callback_data=f"{kind}:reject:{thread_id}") + ) + return ikb.as_markup() diff --git a/bot/keyboards/inline/__init__.py b/bot/keyboards/inline/__init__.py new file mode 100644 index 0000000..ca2e2a9 --- /dev/null +++ b/bot/keyboards/inline/__init__.py @@ -0,0 +1 @@ +from .decision import * diff --git a/bot/keyboards/inline/decision.py b/bot/keyboards/inline/decision.py new file mode 100644 index 0000000..e9bb032 --- /dev/null +++ b/bot/keyboards/inline/decision.py @@ -0,0 +1,18 @@ +from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton +from aiogram.utils.keyboard import InlineKeyboardBuilder + + +def decision_keyboard(thread_id: int, kind: str) -> InlineKeyboardMarkup: + """ + Получение клавиатуры Принятия\Отклонить. + + :param thread_id: Айди действия. + :param kind: Вид для клавиатуры. + :return: Инлайн-клавиатуру (Принять, Отклонить). + """ + ikb: InlineKeyboardBuilder = InlineKeyboardBuilder() + ikb.row( + InlineKeyboardButton(text="✅ Принять", callback_data=f"{kind}:accept:{thread_id}"), + InlineKeyboardButton(text="❌ Отклонить", callback_data=f"{kind}:reject:{thread_id}") + ) + return ikb.as_markup() diff --git a/bot/keyboards/reply.py b/bot/keyboards/reply.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/keyboards/reply/__init__.py b/bot/keyboards/reply/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/middlewares/__init__.py b/bot/middlewares/__init__.py new file mode 100644 index 0000000..0a3d294 --- /dev/null +++ b/bot/middlewares/__init__.py @@ -0,0 +1,137 @@ +""" +Middleware для бота PrimoGuardBot. + +Порядок выполнения middleware важен: +1. TimingMiddleware - замер времени выполнения +2. LoggingMiddleware - логирование всех событий +3. BanCheckMiddleware - проверка статуса бана (блокирует забаненных) +4. ErrorHandlingMiddleware - обработка ошибок (последний) + +Message-level middleware: +1. RateLimitMiddleware/AntiSpamMiddleware - защита от флуда +2. SubscriptionMiddleware - проверка подписки на каналы +3. ReferralMiddleware - обработка реферальных ссылок +""" +from aiogram import Dispatcher, Bot + +from configs import settings +from middleware.loggers import logger +from .error_mdw import ErrorHandlingMiddleware +from .logging_mdw import LoggingMiddleware +from .referal_mdw import ReferralMiddleware +from .spam_mdw import AntiSpamMiddleware, spam_stats +from .sub_mdw import SubscriptionMiddleware +from .time_mdw import TimingMiddleware +from .banwords_mdw import BanWordsMiddleware + +__all__ = ( + # Middleware классы + "TimingMiddleware", + "LoggingMiddleware", + "ErrorHandlingMiddleware", + "AntiSpamMiddleware", + "SubscriptionMiddleware", + "ReferralMiddleware", + "BanWordsMiddleware", + + # Статистика + "spam_stats", + + # Утилиты + "setup_middlewares", +) + + +def setup_middlewares( + dp: Dispatcher, + bot: Bot, + admin_ids: list[int] = settings.ADMIN_ID+settings.OWNER_ID, + channel_ids: list[int | str] | None = None, + enable_spam_check: bool = False, + enable_subscription_check: bool = False, +) -> dict: + """ + Регистрирует все middleware в диспетчере. + + Args: + dp: Диспетчер aiogram + bot: Экземпляр бота + admin_ids: ID администраторов (для защиты и уведомлений) + channel_ids: ID каналов для проверки подписки + enable_spam_check: Включить антиспам + enable_subscription_check: Включить проверку подписки + + Returns: + dict: Словарь с экземплярами middleware для доступа к методам + """ + channel_ids = channel_ids or [] + + # === UPDATE LEVEL MIDDLEWARE (для всех событий) === + middlewares_updates = [] + instances = {} + + # 1. Timing - замер времени (первый!) + timing_mdw = TimingMiddleware() + middlewares_updates.append(timing_mdw) + instances['timing'] = timing_mdw + + # 2. Logging - логирование всех событий + loggings_mdw = LoggingMiddleware() + middlewares_updates.append(loggings_mdw) + instances['logging'] = loggings_mdw + + # 3. ErrorHandling - обработка ошибок (последний!) + errors_mdw = ErrorHandlingMiddleware(admin_ids=admin_ids) + middlewares_updates.append(errors_mdw) + instances['error'] = errors_mdw + + # === MESSAGE LEVEL MIDDLEWARE (только для сообщений) === + middlewares_msg = [] + + # 1. AntiSpam - защита от флуда (опционально) + if enable_spam_check: + spams_mdw = AntiSpamMiddleware() + middlewares_msg.append(spams_mdw) + instances['spam'] = spams_mdw + + # 2. Subscription - проверка подписки на каналы (опционально) + if enable_subscription_check and channel_ids: + subs_mdw = SubscriptionMiddleware(bot=bot, channels=channel_ids) + middlewares_msg.append(subs_mdw) + instances['subscription'] = subs_mdw + + dp.message.middleware(BanWordsMiddleware()) + + # 3. Referral - обработка реферальных ссылок + referral_mdw = ReferralMiddleware() + middlewares_msg.append(referral_mdw) + instances['referral'] = referral_mdw + + # === РЕГИСТРАЦИЯ MIDDLEWARE === + + # Регистрируем update-level middleware + for middleware in middlewares_updates: + dp.update.middleware(middleware) + + # Регистрируем message-level middleware + for middleware in middlewares_msg: + dp.message.middleware(middleware) + + # Логируем успешную регистрацию + enabled_features = [] + if enable_spam_check: + enabled_features.append("AntiSpam") + if enable_subscription_check: + enabled_features.append("Subscription") + + logger.info( + text=( + f"Middleware зарегистрированы: " + f"Update={len(middlewares_updates)}, " + f"Message={len(middlewares_msg)}, " + f"Функции=[{', '.join(enabled_features) if enabled_features else 'базовые'}]" + ), + log_type="MIDDLEWARE_SETUP" + ) + + return instances diff --git a/bot/middlewares/banwords_mdw.py b/bot/middlewares/banwords_mdw.py new file mode 100644 index 0000000..7f0d327 --- /dev/null +++ b/bot/middlewares/banwords_mdw.py @@ -0,0 +1,337 @@ +""" +Middleware для проверки сообщений на запрещённые слова (банворды). + +Pipeline проверки: +1. Пропускаем админов и служебные сообщения +2. Проверяем whitelist (исключения) +3. Проверяем режим silence (удаляем всё) +4. Проверяем режим conflict (конфликтные слова) +5. Проверяем постоянные банворды (substring, lemma, part) +6. Проверяем временные банворды +7. Если найдено - удаляем, логируем, уведомляем админов +""" +from typing import Callable, Dict, Any, Awaitable, Optional +import re + +from aiogram import BaseMiddleware +from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton +from aiogram.exceptions import TelegramBadRequest + +from configs import settings +from database import get_manager, BanWordType +from bot.special import process_text, extract_words, get_lemma +from middleware.loggers import logger + +__all__ = ("BanWordsMiddleware",) + + +class BanWordsMiddleware(BaseMiddleware): + """ + Middleware для фильтрации сообщений с банвордами. + + Проверяет каждое текстовое сообщение на наличие запрещённых слов, + удаляет спам и уведомляет администраторов. + """ + + def __init__(self): + """Инициализирует middleware""" + super().__init__() + self.manager = get_manager() + + async def __call__( + self, + handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], + event: Message, + data: Dict[str, Any] + ) -> Any: + """ + Обрабатывает входящие сообщения. + + Args: + handler: Следующий обработчик в цепочке + event: Сообщение от пользователя + data: Данные из диспетчера + + Returns: + Any: Результат обработчика или None (если сообщение удалено) + """ + # Пропускаем не-текстовые сообщения + if not event.text and not event.caption: + return await handler(event, data) + + # Получаем текст (из text или caption) + message_text = event.text or event.caption + + # Пропускаем команды (начинаются с /) + if message_text.startswith('/'): + return await handler(event, data) + + # Проверяем, является ли пользователь админом + user_id = event.from_user.id + is_super_admin = user_id in settings.OWNER_ID + is_admin = is_super_admin or self.manager.is_admin_cached(user_id) + + # Админы пропускаются + if is_admin: + return await handler(event, data) + + # Проверяем сообщение на банворды + spam_result = await self._check_message(message_text) + + if spam_result: + # Найден спам - удаляем и уведомляем + await self._handle_spam(event, spam_result) + return None # Не продолжаем обработку + + # Сообщение чистое - пропускаем дальше + return await handler(event, data) + + @staticmethod + def _normalize_for_part_check(text: str) -> str: + """ + Нормализует текст для проверки частей слов. + Удаляет ВСЕ символы кроме букв и цифр, приводит к нижнему регистру. + + Args: + text: Исходный текст + + Returns: + str: Нормализованный текст (только буквы и цифры, нижний регистр) + + Examples: + "@Astrixkeepbot" -> "astrixkeepbot" + "hello@world.com" -> "helloworldcom" + "test_123-456" -> "test123456" + """ + # Оставляем только буквы и цифры + return re.sub(r'[^a-zA-Zа-яА-ЯёЁ0-9]', '', text.lower()) + + async def _check_message(self, text: str) -> Optional[Dict[str, str]]: + """ + Проверяет сообщение на наличие банвордов. + + Args: + text: Текст сообщения + + Returns: + Optional[Dict]: {"word": "найденное_слово", "type": "тип_проверки"} или None + """ + # Нормализуем текст для проверки + text_lower = text.lower() + text_processed = process_text(text_lower) + + # === 1. WHITELIST (исключения) === + if self.manager.is_whitelisted(text_processed): + logger.debug( + f"Сообщение содержит whitelist слово: '{text_processed[:50]}'", + log_type="BANWORDS" + ) + return None + + # === 2. SILENCE MODE (удаляем всё) === + if await self.manager.is_silence_active(): + return { + "word": "[режим тишины]", + "type": "silence" + } + + # === 3. CONFLICT MODE (конфликтные слова) === + if await self.manager.is_conflict_active(): + # Проверяем конфликтные подстроки + conflict_substring = self.manager.get_banwords_cached( + BanWordType.CONFLICT_SUBSTRING + ) + for word in conflict_substring: + if word in text_processed: + return {"word": word, "type": "conflict_substring"} + + # Проверяем конфликтные леммы + conflict_lemma = self.manager.get_banwords_cached( + BanWordType.CONFLICT_LEMMA + ) + words_in_text = extract_words(text_processed) + for word_text in words_in_text: + lemma = get_lemma(word_text) + if lemma in conflict_lemma: + return {"word": lemma, "type": "conflict_lemma"} + + # === 4. SUBSTRING (подстроки) === + substring_words = self.manager.get_banwords_cached(BanWordType.SUBSTRING) + for word in substring_words: + if word in text_processed: + return {"word": word, "type": "substring"} + + # === 5. PART (части слов без пробелов и спецсимволов) === + part_words = self.manager.get_banwords_cached(BanWordType.PART) + if part_words: + # Специальная нормализация для PART: удаляем ВСЁ кроме букв и цифр + text_normalized = self._normalize_for_part_check(text) + + logger.debug( + f"Проверка PART: исходный='{text[:50]}', нормализованный='{text_normalized[:50]}'", + log_type="BANWORDS" + ) + + for part in part_words: + # Нормализуем само запрещенное слово тоже + part_normalized = self._normalize_for_part_check(part) + + if part_normalized in text_normalized: + logger.info( + f"Найдена запрещенная часть: '{part}' (нормализовано: '{part_normalized}') " + f"в тексте '{text_normalized[:100]}'", + log_type="BANWORDS" + ) + return {"word": part, "type": "part"} + + # === 6. LEMMA (нормальные формы слов) === + lemma_words = self.manager.get_banwords_cached(BanWordType.LEMMA) + if lemma_words: + words_in_text = extract_words(text_processed) + for word_text in words_in_text: + lemma = get_lemma(word_text) + if lemma in lemma_words: + return {"word": lemma, "type": "lemma"} + + # Банворды не найдены + return None + + async def _handle_spam( + self, + message: Message, + spam_result: Dict[str, str] + ) -> None: + """ + Обрабатывает найденный спам: удаляет, логирует, уведомляет. + + Args: + message: Сообщение со спамом + spam_result: Результат проверки (слово + тип) + """ + user = message.from_user + matched_word = spam_result["word"] + match_type = spam_result["type"] + + # Получаем текст сообщения + message_text = message.text or message.caption or "[нет текста]" + + # === 1. УДАЛЯЕМ СООБЩЕНИЕ === + try: + await message.delete() + logger.info( + f"Удалено сообщение от @{user.username or user.id} " + f"(слово: '{matched_word}', тип: {match_type})", + log_type="BANWORDS", + message=message + ) + except TelegramBadRequest as e: + logger.error( + f"Не удалось удалить сообщение: {e}", + log_type="ERROR", + message=message + ) + return + + # === 2. ЛОГИРУЕМ В БД === + await self.manager.log_spam( + user_id=user.id, + username=user.username or f"id{user.id}", + chat_id=message.chat.id, + message_text=message_text, + matched_word=matched_word, + match_type=match_type + ) + + # === 3. УВЕДОМЛЯЕМ АДМИНОВ === + await self._notify_admins(message, matched_word, match_type, message_text) + + async def _notify_admins( + self, + message: Message, + matched_word: str, + match_type: str, + message_text: str + ) -> None: + """ + Отправляет уведомление в админский чат с кнопками. + + Args: + message: Удалённое сообщение + matched_word: Слово, по которому сработал фильтр + match_type: Тип проверки + message_text: Текст сообщения + """ + user = message.from_user + username = f"@{user.username}" if user.username else f"ID: {user.id}" + + # Получаем количество предыдущих нарушений + spam_count = await self.manager.get_user_spam_count(user.id) + + # Формируем текст уведомления + notification_text = ( + f"🚫 Удалено сообщение\n\n" + f"👤 Пользователь: {username}\n" + f"🆔 ID: {user.id}\n" + f"📊 Нарушений: {spam_count}\n\n" + f"🔍 Триггер: {matched_word}\n" + f"📝 Тип: {self._get_type_emoji(match_type)} {match_type}\n\n" + f"💬 Текст:\n" + f"{self._escape_html(message_text[:500])}" + ) + + # Создаём клавиатуру с действиями + keyboard = InlineKeyboardMarkup(inline_keyboard=[ + [ + InlineKeyboardButton( + text="🔨 Забанить", + callback_data=f"spam_ban:{user.id}:{message.chat.id}" + ), + InlineKeyboardButton( + text="✅ Закрыть", + callback_data="spam_close" + ) + ], + [ + InlineKeyboardButton( + text="📊 Статистика", + callback_data=f"spam_stats:{user.id}" + ) + ] + ]) + + # Отправляем уведомление + try: + bot = message.bot + await bot.send_message( + chat_id=settings.ADMIN_CHAT_ID, + text=notification_text, + reply_markup=keyboard, + parse_mode="HTML" + ) + except Exception as e: + logger.error( + f"Ошибка отправки уведомления админам: {e}", + log_type="ERROR" + ) + + @staticmethod + def _get_type_emoji(match_type: str) -> str: + """Возвращает эмодзи для типа проверки""" + emoji_map = { + "substring": "🔤", + "lemma": "📖", + "part": "🧩", + "silence": "🔇", + "conflict_substring": "⚔️", + "conflict_lemma": "⚔️" + } + return emoji_map.get(match_type, "❓") + + @staticmethod + def _escape_html(text: str) -> str: + """Экранирует HTML символы для безопасного отображения""" + return ( + text.replace("&", "&") + .replace("<", "<") + .replace(">", ">") + ) diff --git a/bot/middlewares/error_mdw.py b/bot/middlewares/error_mdw.py new file mode 100644 index 0000000..8fecd61 --- /dev/null +++ b/bot/middlewares/error_mdw.py @@ -0,0 +1,674 @@ +""" +Middleware для глобальной обработки ошибок +""" +from typing import Callable, Awaitable, Any, Dict, Optional, List, Set +from datetime import datetime +from collections import defaultdict +from enum import Enum +import traceback + +from aiogram import BaseMiddleware +from aiogram.types import TelegramObject, Message, CallbackQuery, Update +from aiogram.exceptions import ( + TelegramBadRequest, + TelegramForbiddenError, + TelegramNotFound, + TelegramUnauthorizedError, + TelegramRetryAfter, + TelegramAPIError +) + +from middleware.loggers import logger +from bot.utils import ( + username, + format_content_info, + get_content_type, + safe_answer_callback, + format_duration, + format_timestamp +) +from bot.templates import msg + +__all__ = ('ErrorHandlingMiddleware', 'ErrorCategory') + + +class ErrorCategory(str, Enum): + """Категории ошибок""" + TELEGRAM_API = "telegram_api" # Ошибки Telegram API + RATE_LIMIT = "rate_limit" # Rate limiting + PERMISSION = "permission" # Права доступа + VALIDATION = "validation" # Валидация данных + DATABASE = "database" # Ошибки БД + HANDLER = "handler" # Ошибки в хендлерах + UNKNOWN = "unknown" # Неизвестные ошибки + + +class ErrorStats: + """Статистика ошибок""" + + def __init__(self): + # Счетчики по категориям + self.by_category: Dict[ErrorCategory, int] = defaultdict(int) + + # Счетчики по типам исключений + self.by_exception: Dict[str, int] = defaultdict(int) + + # Последние ошибки (последние 10) + self.recent_errors: List[Dict[str, Any]] = [] + self.max_recent = 10 + + # Общая статистика + self.total_errors: int = 0 + self.start_time: datetime = datetime.now() + + def add_error( + self, + exception: Exception, + category: ErrorCategory, + user_id: Optional[int] = None, + details: Optional[Dict] = None + ): + """Добавляет ошибку в статистику""" + self.total_errors += 1 + self.by_category[category] += 1 + self.by_exception[type(exception).__name__] += 1 + + # Добавляем в последние ошибки + error_info = { + 'timestamp': datetime.now(), + 'exception': type(exception).__name__, + 'message': str(exception), + 'category': category, + 'user_id': user_id, + 'details': details or {} + } + + self.recent_errors.append(error_info) + if len(self.recent_errors) > self.max_recent: + self.recent_errors.pop(0) + + def get_summary(self) -> Dict[str, Any]: + """Возвращает сводку по статистике""" + uptime = datetime.now() - self.start_time + + return { + 'total_errors': self.total_errors, + 'uptime': format_duration(int(uptime.total_seconds())), + 'by_category': dict(self.by_category), + 'by_exception': dict(self.by_exception), + 'recent_errors': self.recent_errors + } + + +class ErrorHandlingMiddleware(BaseMiddleware): + """ + Middleware для глобальной обработки ошибок. + + Features: + - Категоризация ошибок + - Уведомление администраторов + - Статистика ошибок + - Rate limiting уведомлений + - Retry механизм для некоторых ошибок + - Детальное логирование + - Graceful degradation + """ + + def __init__( + self, + admin_ids: List[int], + notify_admins: bool = True, + notify_users: bool = True, + log_errors: bool = True, + notify_rate_limit: int = 60 # Не чаще раза в минуту для одного типа ошибки + ): + """ + Args: + admin_ids: Список ID администраторов + notify_admins: Уведомлять администраторов + notify_users: Уведомлять пользователей + log_errors: Логировать ошибки + notify_rate_limit: Минимальный интервал между уведомлениями (секунды) + """ + super().__init__() + self.admin_ids = admin_ids + self.notify_admins = notify_admins + self.notify_users = notify_users + self.log_errors = log_errors + self.notify_rate_limit = notify_rate_limit + + # Статистика + self.stats = ErrorStats() + + # Rate limiting для уведомлений + # {error_type: last_notification_time} + self._last_notifications: Dict[str, datetime] = {} + + # Игнорируемые ошибки (для которых не нужно уведомлять) + self.ignored_errors: Set[type] = { + TelegramRetryAfter, # Rate limit Telegram + } + + async def __call__( + self, + handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + event: TelegramObject, + data: Dict[str, Any] + ) -> Any: + """ + Обрабатывает ошибки в хендлерах. + + Args: + handler: Следующий обработчик + event: Входящее событие + data: Контекстные данные + + Returns: + Результат выполнения обработчика или None при ошибке + """ + try: + # Выполняем хендлер + return await handler(event, data) + + except Exception as e: + # Обрабатываем ошибку + await self._handle_error(e, event, data) + return None + + async def _handle_error( + self, + exception: Exception, + event: TelegramObject, + data: Dict[str, Any] + ): + """ + Централизованная обработка ошибки. + + Args: + exception: Исключение + event: Событие + data: Контекстные данные + """ + # Определяем категорию ошибки + category = self._categorize_error(exception) + + # Извлекаем информацию о событии + event_info = self._extract_event_info(event) + + # Добавляем в статистику + self.stats.add_error( + exception=exception, + category=category, + user_id=event_info.get('user_id'), + details=event_info + ) + + # Логируем ошибку + if self.log_errors: + await self._log_error(exception, category, event_info) + + # Уведомляем администраторов + if self.notify_admins and not self._is_ignored(exception): + await self._notify_admins_about_error(exception, category, event_info, event) + + # Уведомляем пользователя + if self.notify_users: + await self._notify_user_about_error(exception, category, event) + + @staticmethod + def _categorize_error(exception: Exception) -> ErrorCategory: + """ + Определяет категорию ошибки. + + Args: + exception: Исключение + + Returns: + Категория ошибки + """ + # Ошибки Telegram API + if isinstance(exception, TelegramRetryAfter): + return ErrorCategory.RATE_LIMIT + + if isinstance(exception, (TelegramForbiddenError, TelegramUnauthorizedError)): + return ErrorCategory.PERMISSION + + if isinstance(exception, (TelegramBadRequest, TelegramNotFound)): + return ErrorCategory.TELEGRAM_API + + if isinstance(exception, TelegramAPIError): + return ErrorCategory.TELEGRAM_API + + # Ошибки валидации + if isinstance(exception, (ValueError, TypeError, AttributeError)): + return ErrorCategory.VALIDATION + + # Ошибки БД (примеры, замени на свои) + # if isinstance(exception, (DatabaseError, OperationalError)): + # return ErrorCategory.DATABASE + + # Остальные ошибки + return ErrorCategory.HANDLER + + @staticmethod + def _extract_event_info(event: TelegramObject) -> Dict[str, Any]: + """ + Извлекает информацию о событии. + + Args: + event: Объект события + + Returns: + Словарь с информацией + """ + info: Dict[str, Any] = { + 'event_type': type(event).__name__, + 'timestamp': datetime.now(), + 'user_str': '@System', + 'user_id': None, + 'chat_id': None, + 'chat_type': None, + 'message_id': None, + 'content_type': None, + 'content_info': None, + 'text': None + } + + # Обработка разных типов событий + message = None + + if isinstance(event, Message): + message = event + elif isinstance(event, CallbackQuery): + message = event.message + info['callback_data'] = event.data + elif isinstance(event, Update): + message = ( + event.message or + event.edited_message or + event.channel_post or + event.edited_channel_post + ) + + if event.callback_query: + info['callback_data'] = event.callback_query.data + + # Извлекаем информацию из сообщения + if message: + # Пользователь + if message.from_user: + info['user_str'] = username(message) + info['user_id'] = message.from_user.id + + # Чат + info['chat_id'] = message.chat.id + info['chat_type'] = message.chat.type + info['message_id'] = message.message_id + + # Контент + info['content_type'] = get_content_type(message) + info['content_info'] = format_content_info(message, include_text=False) + + # Текст + if message.text: + text = message.text + info['text'] = text if len(text) <= 100 else text[:100] + "..." + elif message.caption: + caption = message.caption + info['caption'] = caption if len(caption) <= 100 else caption[:100] + "..." + + return info + + @staticmethod + async def _log_error( + exception: Exception, + category: ErrorCategory, + event_info: Dict[str, Any] + ): + """ + Логирует ошибку. + + Args: + exception: Исключение + category: Категория ошибки + event_info: Информация о событии + """ + # Формируем сообщение для лога + error_type = type(exception).__name__ + error_msg = str(exception) + + # Получаем traceback + tb = ''.join(traceback.format_exception( + type(exception), + exception, + exception.__traceback__ + )) + + # Базовое сообщение + log_msg = ( + f"🚨 Ошибка в хендлере\n" + f"├─ Тип: {error_type}\n" + f"├─ Категория: {category.value}\n" + f"├─ Сообщение: {error_msg}\n" + f"├─ Событие: {event_info['event_type']}\n" + ) + + if event_info.get('text'): + log_msg += f"├─ Текст: {event_info['text']}\n" + + if event_info.get('callback_data'): + log_msg += f"├─ Callback: {event_info['callback_data']}\n" + + if event_info.get('content_info'): + log_msg += f"└─ Контент: {event_info['content_info']}" + + # Логируем с полным traceback + logger.error( + text=log_msg, + log_type=f"ERROR_{category.value.upper()}", + user=event_info['user_str'], + ) + + # Дополнительно логируем traceback отдельно для детального анализа + logger.debug( + text=f"Полный traceback:\n{tb}", + log_type=f"ERROR_{category.value.upper()}_TRACEBACK", + user=event_info['user_str'] + ) + + async def _notify_admins_about_error( + self, + exception: Exception, + category: ErrorCategory, + event_info: Dict[str, Any], + event: TelegramObject + ): + """ + Уведомляет администраторов об ошибке. + + Args: + exception: Исключение + category: Категория ошибки + event_info: Информация о событии + event: Объект события + """ + # Проверяем rate limit + error_key = type(exception).__name__ + + if not self._should_notify(error_key): + logger.debug( + f"Пропуск уведомления админов о {error_key} (rate limit)", + log_type="ADMIN_NOTIFY_SKIP" + ) + return + + # Обновляем время последнего уведомления + self._last_notifications[error_key] = datetime.now() + + # Получаем bot + bot = event.bot if hasattr(event, 'bot') else None + if not bot: + return + + # Формируем сообщение + error_type = type(exception).__name__ + error_msg = str(exception) + + # Определяем emoji для категории + category_emoji = self._get_category_emoji(category) + + notification = ( + f"{category_emoji} Ошибка в боте\n\n" + f"📊 Информация:\n" + f"├─ Тип: {error_type}\n" + f"├─ Категория: {category.value}\n" + f"├─ Время: {format_timestamp(datetime.now())}\n" + ) + + # Добавляем информацию о пользователе + if event_info.get('user_str') and event_info['user_str'] != '@System': + notification += f"└─ Пользователь: {event_info['user_str']}\n\n" + else: + notification += "\n" + + # Добавляем сообщение ошибки + if len(error_msg) <= 200: + notification += f"💬 Сообщение:\n{error_msg}\n\n" + else: + notification += f"💬 Сообщение:\n{error_msg[:200]}...\n\n" + + # Добавляем контекст события + notification += f"📋 Контекст:\n" + + if event_info.get('text'): + notification += f"├─ Текст: {event_info['text']}\n" + + if event_info.get('callback_data'): + notification += f"├─ Callback: {event_info['callback_data']}\n" + + if event_info.get('content_info'): + notification += f"├─ Контент: {event_info['content_info']}\n" + + if event_info.get('chat_type'): + notification += f"└─ Тип чата: {event_info['chat_type']}\n" + + # Добавляем статистику + stats = self.stats.get_summary() + notification += ( + f"\n📊 Статистика:\n" + f"└─ Всего ошибок: {stats['total_errors']}" + ) + + # Отправляем администраторам + for admin_id in self.admin_ids: + try: + await bot.send_message( + chat_id=admin_id, + text=notification, + parse_mode="HTML" + ) + + logger.debug( + f"Администратор {admin_id} уведомлен об ошибке", + log_type="ADMIN_NOTIFIED" + ) + + except Exception as e: + logger.error( + f"Не удалось уведомить админа {admin_id}: {e}", + log_type="ADMIN_NOTIFY_ERROR" + ) + + @staticmethod + async def _notify_user_about_error( + exception: Exception, + category: ErrorCategory, + event: TelegramObject + ): + """ + Уведомляет пользователя об ошибке. + + Args: + exception: Исключение + category: Категория ошибки + event: Объект события + """ + # Формируем сообщение в зависимости от категории + error_messages = { + ErrorCategory.TELEGRAM_API: ( + "⚠️ Произошла техническая ошибка.\n" + "Попробуйте повторить действие." + ), + ErrorCategory.RATE_LIMIT: ( + "⏳ Слишком много запросов.\n" + "Пожалуйста, подождите немного." + ), + ErrorCategory.PERMISSION: ( + "🔒 Недостаточно прав для выполнения действия." + ), + ErrorCategory.VALIDATION: ( + "❌ Некорректные данные.\n" + "Проверьте правильность ввода." + ), + ErrorCategory.DATABASE: ( + "💾 Ошибка базы данных.\n" + "Попробуйте позже." + ), + ErrorCategory.HANDLER: ( + "⚠️ Произошла непредвиденная ошибка.\n" + "Разработчики уже уведомлены." + ), + ErrorCategory.UNKNOWN: ( + "⚠️ Произошла ошибка.\n" + "Попробуйте повторить позже." + ) + } + + error_text = error_messages.get( + category, + error_messages[ErrorCategory.UNKNOWN] + ) + + error_text += "\n\nПопробуйте нажать /start или обратитесь к администратору." + + try: + # Отправляем сообщение + if isinstance(event, Message): + await msg(event, text=error_text) + + elif isinstance(event, CallbackQuery): + await safe_answer_callback(event, error_text[:200], show_alert=True) + + # Также отправляем в чат если сообщение доступно + if event.message: + try: + await msg(event.message, text=error_text) + except: + pass + + elif isinstance(event, Update): + if event.message: + await msg(event.message, text=error_text) + elif event.callback_query: + await safe_answer_callback( + event.callback_query, + error_text[:200], + show_alert=True + ) + + logger.debug( + "Пользователь уведомлен об ошибке", + log_type="USER_ERROR_NOTIFIED" + ) + + except Exception as e: + logger.warning( + f"Не удалось уведомить пользователя об ошибке: {e}", + log_type="USER_NOTIFY_ERROR" + ) + + def _should_notify(self, error_key: str) -> bool: + """ + Проверяет, нужно ли отправлять уведомление (rate limiting). + + Args: + error_key: Ключ ошибки + + Returns: + True если можно отправить уведомление + """ + if error_key not in self._last_notifications: + return True + + last_time = self._last_notifications[error_key] + time_passed = (datetime.now() - last_time).total_seconds() + + return time_passed >= self.notify_rate_limit + + def _is_ignored(self, exception: Exception) -> bool: + """ + Проверяет, игнорируется ли ошибка. + + Args: + exception: Исключение + + Returns: + True если ошибка игнорируется + """ + return type(exception) in self.ignored_errors + + @staticmethod + def _get_category_emoji(category: ErrorCategory) -> str: + """Возвращает emoji для категории ошибки""" + emoji_map = { + ErrorCategory.TELEGRAM_API: "🔌", + ErrorCategory.RATE_LIMIT: "⏳", + ErrorCategory.PERMISSION: "🔒", + ErrorCategory.VALIDATION: "❌", + ErrorCategory.DATABASE: "💾", + ErrorCategory.HANDLER: "🚨", + ErrorCategory.UNKNOWN: "⚠️" + } + + return emoji_map.get(category, "⚠️") + + def get_stats(self) -> Dict[str, Any]: + """Возвращает статистику ошибок""" + return self.stats.get_summary() + + def reset_stats(self): + """Сбрасывает статистику""" + self.stats = ErrorStats() + + def add_ignored_error(self, error_type: type): + """Добавляет тип ошибки в игнорируемые""" + self.ignored_errors.add(error_type) + + def remove_ignored_error(self, error_type: type): + """Удаляет тип ошибки из игнорируемых""" + self.ignored_errors.discard(error_type) + + +# ================= УТИЛИТЫ ================= + +def format_error_stats(stats: Dict[str, Any]) -> str: + """ + Форматирует статистику ошибок. + + Args: + stats: Словарь со статистикой + + Returns: + Отформатированная строка + + Example: + >> stats = middleware.get_stats() + >> print(format_error_stats(stats)) + """ + text = ( + f"🚨 Статистика ошибок\n\n" + f"📊 Общая информация:\n" + f"├─ Всего ошибок: {stats['total_errors']}\n" + f"└─ Время работы: {stats['uptime']}\n\n" + ) + + # По категориям + if stats['by_category']: + text += f"📁 По категориям:\n" + for category, count in stats['by_category'].items(): + text += f"├─ {category}: {count}\n" + text += "\n" + + # По типам исключений + if stats['by_exception']: + text += f"🔧 По типам (топ-5):\n" + sorted_exceptions = sorted( + stats['by_exception'].items(), + key=lambda x: x[1], + reverse=True + )[:5] + + for exc_type, count in sorted_exceptions: + text += f"├─ {exc_type}: {count}\n" + + return text diff --git a/bot/middlewares/logging_mdw.py b/bot/middlewares/logging_mdw.py new file mode 100644 index 0000000..5cc1299 --- /dev/null +++ b/bot/middlewares/logging_mdw.py @@ -0,0 +1,350 @@ +""" +Middleware для логирования всех событий бота +""" +from typing import Callable, Awaitable, Any, Dict, Optional, Tuple +from datetime import datetime + +from aiogram import BaseMiddleware +from aiogram.types import ( + TelegramObject, + Update, + Message, + CallbackQuery, + InlineQuery, + ChatMemberUpdated +) + +from middleware.loggers import logger +from ..utils import ( + username, + get_content_type, + is_command, + parse_command, + is_group_chat +) + +__all__ = ('LoggingMiddleware',) + + +class LoggingMiddleware(BaseMiddleware): + """ + Middleware для детального логирования всех событий бота. + + Типы логов: + - CMD: Команды бота + - MSG: Текстовые сообщения + - MEDIA: Медиа сообщения + - CBD: Callback queries + - INLINE: Inline queries + - MEMBER: Изменения участников чата + """ + + def __init__(self, project_prefix: str = "PRIMO"): + super().__init__() + self.project_prefix = project_prefix + + # Статистика + self.stats = { + 'total': 0, + 'commands': 0, + 'messages': 0, + 'callbacks': 0, + 'errors': 0 + } + + async def __call__( + self, + handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + event: TelegramObject, + data: Dict[str, Any] + ) -> Any: + """Обрабатывает входящее событие""" + self.stats['total'] += 1 + start_time = datetime.now() + + # Анализируем событие + log_info = self._analyze_event(event) + + if not log_info: + return await handler(event, data) + + log_type, log_text, user_str = log_info + + # Добавляем префикс проекта + prefixed_log_type = f"{self.project_prefix}-{log_type}" + + # Логируем получение события + logger.info(text=log_text, log_type=prefixed_log_type, user=user_str) + + try: + # Выполняем обработчик + result = await handler(event, data) + + # Вычисляем время обработки + processing_time = (datetime.now() - start_time).total_seconds() + + # Логируем успешное выполнение для команд + if log_type == "CMD": + self.stats['commands'] += 1 + logger.debug( + text=f"✅ Команда обработана за {processing_time:.3f}s", + log_type=prefixed_log_type, + user=user_str + ) + + return result + + except Exception as e: + self.stats['errors'] += 1 + logger.error( + text=f"❌ Ошибка обработки: {str(e)}", + log_type=prefixed_log_type, + user=user_str, + ) + raise + + def _analyze_event(self, event: TelegramObject) -> Optional[Tuple[str, str, str]]: + """ + Анализирует событие и извлекает информацию для логирования. + + Returns: + Tuple: (тип_лога, текст_лога, пользователь) или None + """ + if isinstance(event, Update): + return self._analyze_update(event) + elif isinstance(event, Message): + return self._analyze_message(event) + elif isinstance(event, CallbackQuery): + return self._analyze_callback(event) + elif isinstance(event, InlineQuery): + return self._analyze_inline_query(event) + elif isinstance(event, ChatMemberUpdated): + return self._analyze_member_update(event) + + return None + + def _analyze_update(self, update: Update) -> Optional[Tuple[str, str, str]]: + """Анализирует Update объект""" + if update.message: + return self._analyze_message(update.message) + elif update.edited_message: + result = self._analyze_message(update.edited_message) + if result: + log_type, log_text, user_str = result + log_text = f"✏️ [РЕДАКТИРОВАНО] {log_text}" + return log_type, log_text, user_str + elif update.channel_post: + return self._analyze_message(update.channel_post, is_channel=True) + elif update.edited_channel_post: + result = self._analyze_message(update.edited_channel_post, is_channel=True) + if result: + log_type, log_text, user_str = result + log_text = f"✏️ [РЕДАКТИРОВАНО] {log_text}" + return log_type, log_text, user_str + elif update.callback_query: + return self._analyze_callback(update.callback_query) + elif update.inline_query: + return self._analyze_inline_query(update.inline_query) + elif update.my_chat_member: + return self._analyze_member_update(update.my_chat_member) + elif update.chat_member: + return self._analyze_member_update(update.chat_member) + + return None + + def _analyze_message(self, message: Message, is_channel: bool = False) -> Tuple[str, str, str]: + """Анализирует сообщение""" + user_str = username(message) + + # Формируем префикс с информацией о чате + chat_info = "" + if is_group_chat(message): + chat_info = f"[{message.chat.type.upper()} {message.chat.id}] " + elif is_channel: + chat_info = f"[CHANNEL {message.chat.id}] " + else: + chat_info = f"[PM {message.chat.id}] " + + # Проверяем команду + if message.text and is_command(message.text): + self.stats['messages'] += 1 + parsed = parse_command(message.text) + + if parsed: + log_text = f"{chat_info}📝 Команда: /{parsed.command}" + + if parsed.args: + args_str = ' '.join(parsed.args[:3]) + if len(parsed.args) > 3: + args_str += f" ... (+{len(parsed.args) - 3})" + log_text += f" | Аргументы: {args_str}" + + if parsed.flags: + flags_str = ', '.join(f"--{k}" for k in list(parsed.flags.keys())[:3]) + if len(parsed.flags) > 3: + flags_str += f" ... (+{len(parsed.flags) - 3})" + log_text += f" | Флаги: {flags_str}" + + return "CMD", log_text, user_str + + # Обычное сообщение + self.stats['messages'] += 1 + + content_type = get_content_type(message, russian=True) + content_emoji = self._get_content_emoji(message) + + # Текстовое сообщение + if message.text: + text_preview = message.text + if len(text_preview) > 100: + text_preview = text_preview[:100] + "..." + + log_text = f"{chat_info}{content_emoji} Сообщение ({len(message.text)} симв.): {text_preview!r}" + + # Медиа с caption + elif message.caption: + caption_preview = message.caption + if len(caption_preview) > 50: + caption_preview = caption_preview[:50] + "..." + + log_text = f"{chat_info}{content_emoji} {content_type}" + + # Добавляем детали медиа + media_details = self._get_media_details_str(message) + if media_details: + log_text += f" {media_details}" + + log_text += f" | Описание: {caption_preview!r}" + + # Медиа без caption + else: + log_text = f"{chat_info}{content_emoji} {content_type}" + + media_details = self._get_media_details_str(message) + if media_details: + log_text += f" {media_details}" + + # Определяем тип лога + log_type = "MEDIA" if message.content_type != "text" else "MSG" + + # Добавляем префикс канала + if is_channel: + log_text = f"📢 {log_text}" + + return log_type, log_text, user_str + + def _analyze_callback(self, callback: CallbackQuery) -> Tuple[str, str, str]: + """Анализирует callback query""" + self.stats['callbacks'] += 1 + + user_str = f"@{callback.from_user.username}" if callback.from_user.username else f"id{callback.from_user.id}" + + callback_data = callback.data or "None" + if len(callback_data) > 50: + callback_data = callback_data[:50] + "..." + + chat_info = f"[MSG {callback.message.message_id}] " if callback.message else "" + log_text = f"{chat_info}🔘 Callback: {callback_data!r}" + + return "CBD", log_text, user_str + + @staticmethod + def _analyze_inline_query(inline_query: InlineQuery) -> Tuple[str, str, str]: + """Анализирует inline query""" + user_str = f"@{inline_query.from_user.username}" if inline_query.from_user.username else f"id{inline_query.from_user.id}" + + query = inline_query.query or "" + if len(query) > 50: + query = query[:50] + "..." + + log_text = f"🔍 Inline запрос: {query!r}" + + return "INLINE", log_text, user_str + + @staticmethod + def _analyze_member_update(update: ChatMemberUpdated) -> Tuple[str, str, str]: + """Анализирует изменения участников""" + user_str = f"@{update.from_user.username}" if update.from_user.username else f"id{update.from_user.id}" + + old_status = update.old_chat_member.status + new_status = update.new_chat_member.status + + chat_info = f"[{update.chat.type.upper()} {update.chat.id}] " + log_text = f"{chat_info}👥 Изменение статуса: {old_status} → {new_status}" + + return "MEMBER", log_text, user_str + + @staticmethod + def _get_content_emoji(message: Message) -> str: + """Возвращает emoji для типа контента""" + emoji_map = { + 'text': '💬', + 'photo': '📷', + 'video': '🎥', + 'animation': '🎞️', + 'audio': '🎵', + 'voice': '🎤', + 'video_note': '🎬', + 'document': '📄', + 'sticker': '🎨', + 'location': '📍', + 'contact': '👤', + 'poll': '📊', + 'dice': '🎲' + } + + return emoji_map.get(message.content_type, '📎') + + @staticmethod + def _get_media_details_str(message: Message) -> Optional[str]: + """Возвращает строку с деталями медиа файла""" + from ..utils import get_media_info + + try: + media_info = get_media_info(message) + details = [] + + # Размер файла + if 'file_size_mb' in media_info: + details.append(f"{media_info['file_size_mb']} MB") + elif 'file_size_kb' in media_info: + details.append(f"{media_info['file_size_kb']} KB") + + # Длительность + if 'duration_formatted' in media_info: + details.append(media_info['duration_formatted']) + + # Разрешение + if 'width' in media_info and 'height' in media_info: + details.append(f"{media_info['width']}x{media_info['height']}") + + return f"({', '.join(details)})" if details else None + + except: + return None + + def get_stats(self) -> Dict[str, int]: + """Возвращает статистику middleware""" + return self.stats.copy() + + def reset_stats(self): + """Сбрасывает статистику""" + self.stats = { + 'total': 0, + 'commands': 0, + 'messages': 0, + 'callbacks': 0, + 'errors': 0 + } + + +def format_log_stats(stats: Dict[str, int]) -> str: + """Форматирует статистику для вывода""" + return ( + f"📊 Статистика логирования:\n" + f"├─ 📨 Всего событий: {stats['total']}\n" + f"├─ 📝 Команд: {stats['commands']}\n" + f"├─ 💬 Сообщений: {stats['messages']}\n" + f"├─ 🔘 Callbacks: {stats['callbacks']}\n" + f"└─ ❌ Ошибок: {stats['errors']}" + ) diff --git a/bot/middlewares/referal_mdw.py b/bot/middlewares/referal_mdw.py new file mode 100644 index 0000000..3ef50a8 --- /dev/null +++ b/bot/middlewares/referal_mdw.py @@ -0,0 +1,544 @@ +""" +Middleware для обработки реферальных ссылок и deep links +""" +from typing import Callable, Awaitable, Any, Dict, Optional +from dataclasses import dataclass, field +from datetime import datetime +from collections import defaultdict +import re + +from aiogram import BaseMiddleware +from aiogram.filters.command import CommandObject +from aiogram.types import TelegramObject, Message, User + +from middleware.loggers import logger + +__all__ = ( + 'ReferralMiddleware', + 'DeepLinkData', + 'referral_stats', + 'ReferralType' +) + + +class ReferralType: + """Типы реферальных ссылок""" + REFERRAL = 'ref' # Обычная реферальная ссылка + PROMO = 'promo' # Промокод + UTM = 'utm' # UTM метки + INVITE = 'invite' # Инвайт-ссылка + DEEPLINK = 'deeplink' # Произвольный deep link + CUSTOM = 'custom' # Кастомный тип + + +@dataclass +class DeepLinkData: + """ + Данные deep link. + + Attributes: + raw: Исходная строка (все после /start) + type: Тип ссылки (ref, promo, utm, и т.д.) + params: Распарсенные параметры + user_id: ID пользователя, перешедшего по ссылке + username: Username пользователя + timestamp: Время перехода + is_valid: Валидна ли ссылка + """ + raw: str + type: str = ReferralType.DEEPLINK + params: Dict[str, Any] = field(default_factory=dict) + user_id: Optional[int] = None + username: Optional[str] = None + timestamp: datetime = field(default_factory=datetime.now) + is_valid: bool = True + + def get(self, key: str, default: Any = None) -> Any: + """Получает параметр по ключу""" + return self.params.get(key, default) + + def __getitem__(self, key: str) -> Any: + """Позволяет использовать data['key']""" + return self.params[key] + + def __contains__(self, key: str) -> bool: + """Позволяет использовать 'key' in data""" + return key in self.params + + +class ReferralStatistics: + """ + Статистика реферальных переходов. + """ + + def __init__(self): + # Счетчики переходов по типам: {type: count} + self.clicks_by_type: Dict[str, int] = defaultdict(int) + + # Переходы по кодам: {ref_code: count} + self.clicks_by_code: Dict[str, int] = defaultdict(int) + + # История переходов: [(timestamp, user_id, ref_code, type), ...] + self.history: list[tuple[datetime, int, str, str]] = [] + + # Уникальные пользователи: {ref_code: set(user_ids)} + self.unique_users: Dict[str, set[int]] = defaultdict(set) + + def record(self, deep_link: DeepLinkData) -> None: + """Записывает переход""" + # Счетчик по типу + self.clicks_by_type[deep_link.type] += 1 + + # Счетчик по коду (если есть реферальный код) + ref_code = deep_link.get('ref_code') or deep_link.get('code') or deep_link.raw + if ref_code: + self.clicks_by_code[ref_code] += 1 + + # Уникальные пользователи + if deep_link.user_id: + self.unique_users[ref_code].add(deep_link.user_id) + + # История + if deep_link.user_id: + self.history.append(( + deep_link.timestamp, + deep_link.user_id, + ref_code, + deep_link.type + )) + + def get_stats(self, ref_code: Optional[str] = None) -> Dict[str, Any]: + """ + Возвращает статистику. + + Args: + ref_code: Код для фильтрации (если None, возвращает общую статистику) + """ + if ref_code: + return { + 'ref_code': ref_code, + 'total_clicks': self.clicks_by_code.get(ref_code, 0), + 'unique_users': len(self.unique_users.get(ref_code, set())) + } + + return { + 'total_clicks': sum(self.clicks_by_type.values()), + 'clicks_by_type': dict(self.clicks_by_type), + 'top_codes': self.get_top_codes(10), + 'total_unique_users': sum(len(users) for users in self.unique_users.values()) + } + + def get_top_codes(self, limit: int = 10) -> list[tuple[str, int]]: + """Возвращает топ реферальных кодов""" + sorted_codes = sorted( + self.clicks_by_code.items(), + key=lambda x: x[1], + reverse=True + ) + return sorted_codes[:limit] + + +# Глобальная статистика +referral_stats = ReferralStatistics() + + +class ReferralMiddleware(BaseMiddleware): + """ + Middleware для обработки реферальных ссылок и deep links. + + Возможности: + - Парсинг различных форматов deep links + - Автоматическое определение типа ссылки + - Валидация параметров + - Сбор статистики + - Интеграция с базой данных через callback + - Поддержка сложных параметров (ref_123_promo_abc) + + Поддерживаемые форматы: + - /start ref123 → {'ref_code': 'ref123'} + - /start promo_SUMMER2024 → {'type': 'promo', 'code': 'SUMMER2024'} + - /start ref_123_bonus_50 → {'ref_code': '123', 'bonus': '50'} + - /start utm_source_telegram → {'utm_source': 'telegram'} + + Attributes: + on_referral: Callback функция для сохранения в БД + validator: Функция валидации кодов + parse_complex: Парсить ли сложные параметры + collect_stats: Собирать ли статистику + + Example: + ```python + from middleware.referral import ReferralMiddleware, DeepLinkData + + async def save_referral(deep_link: DeepLinkData): + # Сохранение в БД + await db.save_referral( + user_id=deep_link.user_id, + ref_code=deep_link.get('ref_code'), + timestamp=deep_link.timestamp + ) + + # Регистрация middleware + referral_mdw = ReferralMiddleware( + on_referral=save_referral, + parse_complex=True, + collect_stats=True + ) + + dp.message.middleware(referral_mdw) + + # В хендлере + @router.message(CommandStart()) + async def start(message: Message, deep_link: Optional[DeepLinkData] = None): + if deep_link: + ref_code = deep_link.get('ref_code') + await message.answer(f"Привет! Вы пришли по ссылке: {ref_code}") + else: + await message.answer("Привет!") + ``` + """ + + # Паттерны для парсинга + PATTERNS = { + # ref_123 или ref123 + ReferralType.REFERRAL: re.compile(r'^ref[_-]?(\w+)$', re.IGNORECASE), + + # promo_SUMMER2024 + ReferralType.PROMO: re.compile(r'^promo[_-]?(\w+)$', re.IGNORECASE), + + # invite_abc123 + ReferralType.INVITE: re.compile(r'^invite[_-]?(\w+)$', re.IGNORECASE), + + # utm_source_telegram_campaign_ads + ReferralType.UTM: re.compile(r'^utm[_-]', re.IGNORECASE), + } + + def __init__( + self, + on_referral: Optional[Callable[[DeepLinkData], Awaitable[None]]] = None, + validator: Optional[Callable[[str], bool]] = None, + parse_complex: bool = True, + collect_stats: bool = True, + max_length: int = 64 + ): + """ + Инициализация middleware. + + Args: + on_referral: Callback для обработки реферала (сохранение в БД) + validator: Функция валидации кода (должна вернуть True если валиден) + parse_complex: Парсить ли сложные параметры (ref_123_bonus_50) + collect_stats: Собирать ли статистику + max_length: Максимальная длина deep link + """ + super().__init__() + self.on_referral = on_referral + self.validator = validator + self.parse_complex = parse_complex + self.collect_stats = collect_stats + self.max_length = max_length + + def _parse_simple(self, args: str) -> tuple[str, Dict[str, Any]]: + """ + Парсит простые форматы deep links. + + Args: + args: Аргументы команды /start + + Returns: + tuple: (тип, параметры) + """ + # Проверка по паттернам + for link_type, pattern in self.PATTERNS.items(): + match = pattern.match(args) + if match: + if link_type == ReferralType.REFERRAL: + return link_type, {'ref_code': match.group(1)} + elif link_type == ReferralType.PROMO: + return link_type, {'code': match.group(1), 'promo_code': match.group(1)} + elif link_type == ReferralType.INVITE: + return link_type, {'invite_code': match.group(1)} + elif link_type == ReferralType.UTM: + # Парсим UTM параметры + return link_type, self._parse_utm(args) + + # Если не совпало ни с одним паттерном - просто код + return ReferralType.DEEPLINK, {'code': args} + + def _parse_utm(self, args: str) -> Dict[str, Any]: + """ + Парсит UTM параметры: utm_source_telegram_campaign_ads + + Args: + args: Строка с UTM параметрами + + Returns: + Dict с UTM параметрами + """ + params = {} + + # Удаляем префикс utm_ + if args.lower().startswith('utm_'): + args = args[4:] + + # Разбиваем по _ и парсим пары ключ-значение + parts = args.split('_') + + i = 0 + while i < len(parts) - 1: + key = f"utm_{parts[i]}" + value = parts[i + 1] + params[key] = value + i += 2 + + return params + + def _parse_complex(self, args: str) -> tuple[str, Dict[str, Any]]: + """ + Парсит сложные форматы: ref_123_bonus_50_promo_SUMMER + + Args: + args: Аргументы команды + + Returns: + tuple: (тип, параметры) + """ + params = {} + parts = args.split('_') + + # Определяем тип по первому элементу + link_type = ReferralType.DEEPLINK + + if parts[0].lower() in ['ref', 'referral']: + link_type = ReferralType.REFERRAL + if len(parts) > 1: + params['ref_code'] = parts[1] + parts = parts[2:] # Пропускаем первые 2 элемента + elif parts[0].lower() == 'promo': + link_type = ReferralType.PROMO + if len(parts) > 1: + params['promo_code'] = parts[1] + parts = parts[2:] + elif parts[0].lower() == 'invite': + link_type = ReferralType.INVITE + if len(parts) > 1: + params['invite_code'] = parts[1] + parts = parts[2:] + + # Парсим остальные параметры как пары ключ-значение + i = 0 + while i < len(parts) - 1: + key = parts[i] + value = parts[i + 1] + + # Пытаемся преобразовать в число + try: + value = int(value) + except ValueError: + try: + value = float(value) + except ValueError: + pass # Оставляем строкой + + params[key] = value + i += 2 + + return link_type, params + + def _validate_deep_link(self, args: str) -> bool: + """ + Валидирует deep link. + + Args: + args: Строка для валидации + + Returns: + bool: True если валиден + """ + # Проверка длины + if len(args) > self.max_length: + logger.warning( + f"Deep link слишком длинный: {len(args)} > {self.max_length}", + log_type='REFERRAL' + ) + return False + + # Проверка на запрещенные символы (только буквы, цифры, _ и -) + if not re.match(r'^[a-zA-Z0-9_-]+$', args): + logger.warning( + f"Deep link содержит недопустимые символы: {args}", + log_type='REFERRAL' + ) + return False + + # Кастомная валидация + if self.validator: + return self.validator(args) + + return True + + def _parse_deep_link(self, args: str, user: User) -> DeepLinkData: + """ + Парсит deep link и создает объект DeepLinkData. + + Args: + args: Аргументы команды /start + user: Пользователь, перешедший по ссылке + + Returns: + DeepLinkData: Распарсенные данные + """ + # Валидация + is_valid = self._validate_deep_link(args) + + # Парсинг + if self.parse_complex and '_' in args: + link_type, params = self._parse_complex(args) + else: + link_type, params = self._parse_simple(args) + + # Создаем объект + deep_link = DeepLinkData( + raw=args, + type=link_type, + params=params, + user_id=user.id, + username=user.username, + is_valid=is_valid + ) + + return deep_link + + async def __call__( + self, + handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + event: TelegramObject, + data: Dict[str, Any] + ) -> Any: + """ + Перехватывает команды /start с аргументами. + + Args: + handler: Функция хендлера + event: Объект события + data: Дополнительные данные + + Returns: + Результат хендлера + """ + # Обрабатываем только сообщения + if not isinstance(event, Message): + return await handler(event, data) + + # Извлекаем команду + command: Optional[CommandObject] = data.get('command') + + # Проверяем, что это /start с аргументами + if not command or command.command.lower() != 'start' or not command.args: + return await handler(event, data) + + user = event.from_user + args = command.args + + # Парсим deep link + deep_link = self._parse_deep_link(args, user) + + # Логирование + if deep_link.is_valid: + logger.info( + f"Deep link: type={deep_link.type}, params={deep_link.params}", + log_type='REFERRAL', + user=f"@{user.username}" if user.username else f"id{user.id}" + ) + else: + logger.warning( + f"Невалидный deep link: {args}", + log_type='REFERRAL', + user=f"@{user.username}" if user.username else f"id{user.id}" + ) + + # Собираем статистику + if self.collect_stats and deep_link.is_valid: + referral_stats.record(deep_link) + + # Вызываем callback для сохранения в БД + if self.on_referral and deep_link.is_valid: + try: + await self.on_referral(deep_link) + except Exception as e: + logger.error( + f"Ошибка в on_referral callback: {e}", + log_type='REFERRAL' + ) + + # Добавляем deep_link в data для хендлера + data['deep_link'] = deep_link + data['ref_code'] = deep_link.get('ref_code') # Для обратной совместимости + + # Выполняем хендлер + return await handler(event, data) + + +# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ================= + +def create_deep_link(bot_username: str, **params) -> str: + """ + Создает deep link для бота. + + Args: + bot_username: Username бота (без @) + **params: Параметры для ссылки + + Returns: + str: Готовая ссылка + + Example: + >>> create_deep_link('mybot', ref_code='123', bonus='50') + 'https://t.me/mybot?start=ref_123_bonus_50' + """ + # Формируем строку параметров + parts = [] + + for key, value in params.items(): + parts.append(str(key)) + parts.append(str(value)) + + param_string = '_'.join(parts) + + return f"https://t.me/{bot_username}?start={param_string}" + + +def create_referral_link(bot_username: str, ref_code: str) -> str: + """ + Создает простую реферальную ссылку. + + Args: + bot_username: Username бота + ref_code: Реферальный код + + Returns: + str: Реферальная ссылка + + Example: + >>> create_referral_link('mybot', '123') + 'https://t.me/mybot?start=ref_123' + """ + return f"https://t.me/{bot_username}?start=ref_{ref_code}" + + +def create_promo_link(bot_username: str, promo_code: str) -> str: + """ + Создает ссылку с промокодом. + + Args: + bot_username: Username бота + promo_code: Промокод + + Returns: + str: Ссылка с промокодом + + Example: + >>> create_promo_link('mybot', 'SUMMER2024') + 'https://t.me/mybot?start=promo_SUMMER2024' + """ + return f"https://t.me/{bot_username}?start=promo_{promo_code}" diff --git a/bot/middlewares/spam_mdw.py b/bot/middlewares/spam_mdw.py new file mode 100644 index 0000000..bcd15b1 --- /dev/null +++ b/bot/middlewares/spam_mdw.py @@ -0,0 +1,575 @@ +""" +Умный middleware для защиты от спама с адаптивными лимитами +""" +from time import time +from typing import Callable, Awaitable, Any, Dict, Optional +from dataclasses import dataclass, field +from datetime import datetime +from collections import Counter + +from aiogram import BaseMiddleware +from aiogram.types import TelegramObject, Message, CallbackQuery + +from middleware.loggers import logger +from configs import settings + +__all__ = ('AntiSpamMiddleware', 'spam_stats') + + +@dataclass +class MessageContext: + """Контекст сообщения для умной детекции""" + text: Optional[str] = None + is_forward: bool = False + is_reply: bool = False + is_command: bool = False + media_type: Optional[str] = None + callback_data: Optional[str] = None + + +@dataclass +class UserSpamStats: + """ + Расширенная статистика спама для пользователя. + """ + user_id: int + request_times: list[float] = field(default_factory=list) + message_contexts: list[MessageContext] = field(default_factory=list) + warnings: int = 0 + blocked_until: Optional[float] = None + total_requests: int = 0 + total_blocks: int = 0 + first_seen: Optional[float] = None + last_seen: Optional[float] = None + reputation: float = 1.0 # Репутация пользователя (0.5 - 2.0) + + def is_blocked(self, current_time: float) -> bool: + """Проверяет, заблокирован ли пользователь""" + if self.blocked_until is None: + return False + + if current_time < self.blocked_until: + return True + + # Разблокировка + self.blocked_until = None + self.warnings = max(0, self.warnings - 1) # Снижаем предупреждения, но не сбрасываем полностью + return False + + def get_remaining_block_time(self, current_time: float) -> float: + """Возвращает оставшееся время блокировки""" + if self.blocked_until is None or current_time >= self.blocked_until: + return 0.0 + return self.blocked_until - current_time + + def clean_old_requests(self, current_time: float, time_window: float) -> None: + """Удаляет старые запросы за пределами временного окна""" + cutoff_time = current_time - time_window + + # Удаляем старые запросы + new_times = [] + new_contexts = [] + + for req_time, context in zip(self.request_times, self.message_contexts): + if req_time > cutoff_time: + new_times.append(req_time) + new_contexts.append(context) + + self.request_times = new_times + self.message_contexts = new_contexts + + def add_request(self, current_time: float, context: MessageContext) -> None: + """Добавляет новый запрос с контекстом""" + self.request_times.append(current_time) + self.message_contexts.append(context) + self.total_requests += 1 + self.last_seen = current_time + + if self.first_seen is None: + self.first_seen = current_time + + def add_warning(self) -> None: + """Добавляет предупреждение и снижает репутацию""" + self.warnings += 1 + self.reputation = max(0.5, self.reputation - 0.1) + + def improve_reputation(self) -> None: + """Улучшает репутацию за хорошее поведение""" + self.reputation = min(2.0, self.reputation + 0.05) + + def block(self, current_time: float, duration: float) -> None: + """Блокирует пользователя""" + self.blocked_until = current_time + duration + self.total_blocks += 1 + self.reputation = max(0.5, self.reputation - 0.3) + + def detect_spam_patterns(self) -> Dict[str, Any]: + """ + Умная детекция спама на основе паттернов. + + Returns: + Dict с результатами анализа + """ + if len(self.message_contexts) < 3: + return {'is_spam': False, 'reason': None, 'severity': 0.0} + + recent_contexts = self.message_contexts[-10:] # Последние 10 сообщений + + # 1. Проверка идентичных текстовых сообщений + texts = [ctx.text for ctx in recent_contexts if ctx.text and not ctx.is_command] + if texts: + text_counts = Counter(texts) + most_common_text, count = text_counts.most_common(1)[0] + + if count >= 5: # 5 одинаковых сообщений подряд + return { + 'is_spam': True, + 'reason': 'identical_messages', + 'severity': 1.0, + 'details': f"Повторяющееся сообщение: '{most_common_text[:50]}...'" + } + + # 2. Проверка спама callback кнопок + callbacks = [ctx.callback_data for ctx in recent_contexts if ctx.callback_data] + if callbacks: + callback_counts = Counter(callbacks) + most_common_callback, count = callback_counts.most_common(1)[0] + + if count >= 8: # 8 нажатий одной кнопки + return { + 'is_spam': True, + 'reason': 'callback_spam', + 'severity': 0.8, + 'details': f"Спам кнопки: {most_common_callback}" + } + + # 3. Проверка флуда медиа + media_types = [ctx.media_type for ctx in recent_contexts if ctx.media_type] + if len(media_types) >= 7: # 7+ медиафайлов подряд + return { + 'is_spam': True, + 'reason': 'media_flood', + 'severity': 0.6, + 'details': f"Флуд медиа: {len(media_types)} файлов" + } + + return {'is_spam': False, 'reason': None, 'severity': 0.0} + + +class SpamStatistics: + """Глобальная статистика по спаму""" + + def __init__(self): + self.users: Dict[int, UserSpamStats] = {} + self.total_blocked_requests: int = 0 + self.total_warnings_issued: int = 0 + + def get_user(self, user_id: int) -> UserSpamStats: + """Получает или создает статистику пользователя""" + if user_id not in self.users: + self.users[user_id] = UserSpamStats(user_id=user_id) + return self.users[user_id] + + def get_top_spammers(self, limit: int = 10) -> list[tuple[int, int]]: + """Возвращает топ спамеров""" + sorted_users = sorted( + self.users.items(), + key=lambda x: x[1].total_blocks, + reverse=True + ) + return [(uid, stats.total_blocks) for uid, stats in sorted_users[:limit]] + + def get_stats_summary(self) -> Dict[str, Any]: + """Возвращает общую статистику""" + return { + 'total_users': len(self.users), + 'total_blocked_requests': self.total_blocked_requests, + 'total_warnings': self.total_warnings_issued, + 'active_blocks': sum( + 1 for stats in self.users.values() + if stats.blocked_until and stats.blocked_until > time() + ) + } + + def cleanup(self, max_age: float = 86400.0) -> int: + """Удаляет старую статистику (24 часа по умолчанию)""" + current_time = time() + cutoff_time = current_time - max_age + + users_to_delete = [ + uid for uid, stats in self.users.items() + if stats.last_seen and stats.last_seen < cutoff_time + and not stats.is_blocked(current_time) + ] + + for uid in users_to_delete: + del self.users[uid] + + return len(users_to_delete) + + +# Глобальная статистика +spam_stats = SpamStatistics() + + +class AntiSpamMiddleware(BaseMiddleware): + """ + Умный антиспам с адаптивными лимитами. + + Особенности: + - Различает типы активности (текст, форварды, команды, callback) + - Адаптивные лимиты в зависимости от типа сообщения + - Система репутации пользователей + - Умная детекция спам-паттернов + - Мягкое отношение к пересылкам и ответам + """ + + def __init__( + self, + # Базовые лимиты + rate_limit_text: int = 8, # Текстовых сообщений за окно + rate_limit_forward: int = 20, # Пересылок за окно + rate_limit_callback: int = 10, # Нажатий кнопок за окно + rate_limit_media: int = 10, # Медиа за окно + + time_window: float = 10.0, # Временное окно (секунды) + + # Предупреждения и блокировки + warning_limit: int = 3, + block_duration: float = 120.0, # 2 минуты базовая блокировка + max_block_duration: float = 3600.0, # 1 час максимум + + # Опции + whitelist_admins: bool = True, + progressive_blocking: bool = True, + enable_smart_detection: bool = True, + enable_reputation: bool = True, + log_all: bool = False + ): + super().__init__() + self.rate_limit_text = rate_limit_text + self.rate_limit_forward = rate_limit_forward + self.rate_limit_callback = rate_limit_callback + self.rate_limit_media = rate_limit_media + self.time_window = time_window + self.warning_limit = warning_limit + self.block_duration = block_duration + self.max_block_duration = max_block_duration + self.whitelist_admins = whitelist_admins + self.progressive_blocking = progressive_blocking + self.enable_smart_detection = enable_smart_detection + self.enable_reputation = enable_reputation + self.log_all = log_all + + def _extract_context(self, event: TelegramObject) -> MessageContext: + """Извлекает контекст из события""" + context = MessageContext() + + if isinstance(event, Message): + context.text = event.text or event.caption + context.is_forward = event.forward_date is not None + context.is_reply = event.reply_to_message is not None + context.is_command = bool(context.text and context.text.startswith('/')) + + # Определяем тип медиа + if event.photo: + context.media_type = 'photo' + elif event.video: + context.media_type = 'video' + elif event.document: + context.media_type = 'document' + elif event.audio: + context.media_type = 'audio' + elif event.voice: + context.media_type = 'voice' + elif event.sticker: + context.media_type = 'sticker' + + elif isinstance(event, CallbackQuery): + context.callback_data = event.data + + return context + + def _get_effective_rate_limit(self, user_stats: UserSpamStats, context: MessageContext) -> int: + """Вычисляет эффективный лимит с учётом типа и репутации""" + # Базовый лимит по типу + if context.is_command: + return 999 # Команды не ограничиваем + elif context.callback_data: + base_limit = self.rate_limit_callback + elif context.is_forward: + base_limit = self.rate_limit_forward + elif context.media_type: + base_limit = self.rate_limit_media + else: + base_limit = self.rate_limit_text + + # Применяем репутацию + if self.enable_reputation: + base_limit = int(base_limit * user_stats.reputation) + + return max(3, base_limit) # Минимум 3 сообщения + + def _calculate_block_duration(self, warnings: int) -> float: + """Вычисляет длительность блокировки""" + if not self.progressive_blocking: + return self.block_duration + + multiplier = 2 ** (warnings // self.warning_limit) + duration = self.block_duration * multiplier + + return min(duration, self.max_block_duration) + + @staticmethod + def _format_duration(seconds: float) -> str: + """Форматирует длительность""" + if seconds < 60: + return f"{int(seconds)} сек" + elif seconds < 3600: + return f"{int(seconds / 60)} мин" + else: + return f"{int(seconds / 3600)} час" + + async def __call__( + self, + handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + event: TelegramObject, + data: Dict[str, Any] + ) -> Optional[Any]: + """Основная логика проверки""" + + # Пропускаем не-сообщения и не-callback + if not isinstance(event, (Message, CallbackQuery)): + return await handler(event, data) + + user_id = event.from_user.id if event.from_user else None + if user_id is None: + return await handler(event, data) + + user_str = f"@{event.from_user.username}" if event.from_user.username else f"id{user_id}" + + # Whitelist для администраторов + if self.whitelist_admins and user_id in (settings.OWNER_ID + settings.ADMIN_ID): + if self.log_all: + logger.debug(f"Администратор {user_str} пропущен", log_type='ANTI_SPAM') + return await handler(event, data) + + current_time = time() + user_stats = spam_stats.get_user(user_id) + + # Проверка блокировки + if user_stats.is_blocked(current_time): + remaining = user_stats.get_remaining_block_time(current_time) + spam_stats.total_blocked_requests += 1 + + logger.warning( + f"Запрос от заблокированного пользователя (осталось {self._format_duration(remaining)})", + log_type='ANTI_SPAM', + user=user_str + ) + + block_message = ( + f"🚫 Вы заблокированы за спам!\n\n" + f"⏳ Оставшееся время: {self._format_duration(remaining)}\n" + f"⚠️ Предупреждений: {user_stats.warnings}" + ) + + if isinstance(event, Message): + await event.answer(block_message, parse_mode="HTML") + elif isinstance(event, CallbackQuery): + await event.answer( + f"🚫 Заблокирован на {self._format_duration(remaining)}", + show_alert=True + ) + + return None + + # Извлекаем контекст сообщения + context = self._extract_context(event) + + # Очищаем старые запросы + user_stats.clean_old_requests(current_time, self.time_window) + + # Умная детекция спам-паттернов + if self.enable_smart_detection: + spam_analysis = user_stats.detect_spam_patterns() + + if spam_analysis['is_spam']: + user_stats.add_warning() + spam_stats.total_warnings_issued += 1 + + logger.warning( + f"Обнаружен спам-паттерн: {spam_analysis['reason']} - {spam_analysis['details']}", + log_type='ANTI_SPAM', + user=user_str + ) + + # Немедленная блокировка при явном спаме + if spam_analysis['severity'] >= 0.9: + block_duration = self._calculate_block_duration(user_stats.warnings) + user_stats.block(current_time, block_duration) + + logger.error( + f"Пользователь заблокирован за спам: {spam_analysis['reason']}", + log_type='ANTI_SPAM', + user=user_str + ) + + block_message = ( + f"🚫 Вы заблокированы за спам!\n\n" + f"⏳ Длительность: {self._format_duration(block_duration)}\n" + f"⚠️ Причина: {spam_analysis['details']}" + ) + + if isinstance(event, Message): + await event.answer(block_message, parse_mode="HTML") + elif isinstance(event, CallbackQuery): + await event.answer( + f"🚫 Блокировка: {spam_analysis['reason']}", + show_alert=True + ) + + return None + + # Получаем эффективный лимит + effective_limit = self._get_effective_rate_limit(user_stats, context) + + # Подсчитываем релевантные запросы + relevant_requests = 0 + for req_context in user_stats.message_contexts: + if context.is_forward and req_context.is_forward: + relevant_requests += 1 + elif context.callback_data and req_context.callback_data: + relevant_requests += 1 + elif context.media_type and req_context.media_type: + relevant_requests += 1 + elif not (req_context.is_forward or req_context.callback_data or req_context.media_type or req_context.is_command): + relevant_requests += 1 + + if self.log_all: + logger.debug( + f"Rate limit: {relevant_requests}/{effective_limit} (тип: {context.media_type or 'text'}, репутация: {user_stats.reputation:.2f})", + log_type='ANTI_SPAM', + user=user_str + ) + + # Проверка лимита + if relevant_requests >= effective_limit: + user_stats.add_warning() + spam_stats.total_warnings_issued += 1 + + logger.warning( + f"Превышен rate limit ({relevant_requests}/{effective_limit}). " + f"Предупреждение {user_stats.warnings}/{self.warning_limit}", + log_type='ANTI_SPAM', + user=user_str + ) + + # Блокировка при достижении лимита предупреждений + if user_stats.warnings >= self.warning_limit: + block_duration = self._calculate_block_duration(user_stats.warnings) + user_stats.block(current_time, block_duration) + + logger.error( + f"Пользователь заблокирован на {self._format_duration(block_duration)}. " + f"Всего блокировок: {user_stats.total_blocks}", + log_type='ANTI_SPAM', + user=user_str + ) + + block_message = ( + f"🚫 Вы заблокированы за спам!\n\n" + f"⏳ Длительность: {self._format_duration(block_duration)}\n" + f"⚠️ Причина: Превышение лимита запросов\n" + f"📊 Это блокировка #{user_stats.total_blocks}" + ) + + if isinstance(event, Message): + await event.answer(block_message, parse_mode="HTML") + elif isinstance(event, CallbackQuery): + await event.answer( + f"🚫 Блокировка на {self._format_duration(block_duration)}", + show_alert=True + ) + + return None + + # Предупреждение + warning_message = ( + f"⚠️ Предупреждение #{user_stats.warnings}\n\n" + f"Вы отправляете запросы слишком часто!\n" + f"Лимит: {effective_limit} запросов за {self._format_duration(self.time_window)}\n\n" + f"При {self.warning_limit} предупреждениях последует блокировка." + ) + + if isinstance(event, Message): + await event.answer(warning_message, parse_mode="HTML") + elif isinstance(event, CallbackQuery): + await event.answer( + f"⚠️ Предупреждение {user_stats.warnings}/{self.warning_limit}", + show_alert=True + ) + + return None + + # Добавляем текущий запрос + user_stats.add_request(current_time, context) + + # Улучшаем репутацию за нормальное поведение + if self.enable_reputation and user_stats.total_requests % 10 == 0: + user_stats.improve_reputation() + + if self.log_all: + logger.debug( + f"Запрос разрешен. Всего: {user_stats.total_requests}, репутация: {user_stats.reputation:.2f}", + log_type='ANTI_SPAM', + user=user_str + ) + + return await handler(event, data) + + +# ================= УПРАВЛЕНИЕ ================= + +async def reset_spam_warnings(user_id: int) -> bool: + """Сбрасывает предупреждения пользователя""" + if user_id in spam_stats.users: + spam_stats.users[user_id].warnings = 0 + spam_stats.users[user_id].blocked_until = None + logger.info(f"Предупреждения сброшены для id{user_id}", log_type='ANTI_SPAM') + return True + return False + + +async def unblock_user(user_id: int) -> bool: + """Разблокирует пользователя""" + if user_id in spam_stats.users: + stats = spam_stats.users[user_id] + if stats.blocked_until: + stats.blocked_until = None + stats.warnings = 0 + logger.info(f"Пользователь id{user_id} разблокирован вручную", log_type='ANTI_SPAM') + return True + return False + + +async def get_user_spam_info(user_id: int) -> Optional[Dict[str, Any]]: + """Получает информацию о спам-статистике пользователя""" + if user_id not in spam_stats.users: + return None + + stats = spam_stats.users[user_id] + current_time = time() + + return { + 'user_id': user_id, + 'warnings': stats.warnings, + 'reputation': stats.reputation, + 'is_blocked': stats.is_blocked(current_time), + 'blocked_until': datetime.fromtimestamp(stats.blocked_until) if stats.blocked_until else None, + 'remaining_block_time': stats.get_remaining_block_time(current_time), + 'total_requests': stats.total_requests, + 'total_blocks': stats.total_blocks, + 'first_seen': datetime.fromtimestamp(stats.first_seen) if stats.first_seen else None, + 'last_seen': datetime.fromtimestamp(stats.last_seen) if stats.last_seen else None + } diff --git a/bot/middlewares/sub_mdw.py b/bot/middlewares/sub_mdw.py new file mode 100644 index 0000000..9f150ac --- /dev/null +++ b/bot/middlewares/sub_mdw.py @@ -0,0 +1,553 @@ +""" +Middleware для проверки подписки пользователей на каналы +""" +from time import time +from typing import Callable, Awaitable, Any, Dict, Optional, Union +from dataclasses import dataclass + +from aiogram import BaseMiddleware, Bot +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError +from aiogram.types import TelegramObject, Message, CallbackQuery, InlineKeyboardButton, Chat +from aiogram.utils.keyboard import InlineKeyboardBuilder +from aiogram.enums import ChatMemberStatus + +from middleware.loggers import logger +from configs import settings + +__all__ = ('SubscriptionMiddleware', 'ChannelConfig') + + +@dataclass +class ChannelConfig: + """ + Конфигурация канала для проверки подписки. + + Attributes: + id: ID или username канала + name: Название канала (для отображения) + invite_link: Пригласительная ссылка + required: Обязательная ли подписка + """ + id: Union[str, int] + name: Optional[str] = None + invite_link: Optional[str] = None + required: bool = True + + +class SubscriptionCache: + """ + Кэш для проверок подписки. + + Уменьшает количество запросов к Telegram API. + """ + + def __init__(self, ttl: float = 300.0): + """ + Args: + ttl: Время жизни кэша в секундах (по умолчанию 5 минут) + """ + self.ttl = ttl + # Структура: {(user_id, channel_id): (is_subscribed, timestamp)} + self._cache: Dict[tuple[int, Union[str, int]], tuple[bool, float]] = {} + + def get(self, user_id: int, channel_id: Union[str, int]) -> Optional[bool]: + """ + Получает значение из кэша. + + Args: + user_id: ID пользователя + channel_id: ID канала + + Returns: + bool или None: True/False если в кэше и актуально, иначе None + """ + key = (user_id, channel_id) + + if key in self._cache: + is_subscribed, timestamp = self._cache[key] + + # Проверяем актуальность + if time() - timestamp < self.ttl: + return is_subscribed + else: + # Удаляем устаревшую запись + del self._cache[key] + + return None + + def set(self, user_id: int, channel_id: Union[str, int], is_subscribed: bool) -> None: + """ + Сохраняет значение в кэш. + + Args: + user_id: ID пользователя + channel_id: ID канала + is_subscribed: Статус подписки + """ + key = (user_id, channel_id) + self._cache[key] = (is_subscribed, time()) + + def invalidate(self, user_id: Optional[int] = None, channel_id: Optional[Union[str, int]] = None) -> None: + """ + Инвалидирует кэш. + + Args: + user_id: ID пользователя (если None, инвалидирует все) + channel_id: ID канала (если None, инвалидирует все для пользователя) + """ + if user_id is None and channel_id is None: + # Полная очистка + self._cache.clear() + elif user_id is not None and channel_id is None: + # Удаляем все записи пользователя + keys_to_delete = [key for key in self._cache if key[0] == user_id] + for key in keys_to_delete: + del self._cache[key] + elif user_id is not None and channel_id is not None: + # Удаляем конкретную запись + key = (user_id, channel_id) + if key in self._cache: + del self._cache[key] + + def cleanup(self) -> int: + """ + Удаляет устаревшие записи. + + Returns: + int: Количество удаленных записей + """ + current_time = time() + keys_to_delete = [ + key for key, (_, timestamp) in self._cache.items() + if current_time - timestamp >= self.ttl + ] + + for key in keys_to_delete: + del self._cache[key] + + return len(keys_to_delete) + + +class SubscriptionMiddleware(BaseMiddleware): + """ + Middleware для проверки подписки пользователя на каналы. + + Возможности: + - Проверка подписки на один или несколько каналов + - Кэширование результатов проверки + - Whitelist для администраторов + - Автоматическое получение ссылок на каналы + - Гибкая настройка обязательных/необязательных каналов + - Красивое сообщение с кнопками подписки + + Attributes: + bot: Экземпляр бота + channels: Список конфигураций каналов + cache_ttl: Время жизни кэша в секундах + whitelist_admins: Пропускать ли администраторов бота + show_buttons: Показывать ли кнопки для подписки + + Example: + ```python + from middleware.subscription import SubscriptionMiddleware, ChannelConfig + + channels = [ + ChannelConfig( + id="@my_channel", + name="Основной канал", + invite_link="https://t.me/my_channel" + ), + ChannelConfig( + id=-1001234567890, + name="Закрытый канал", + required=True + ) + ] + + dp.message.middleware(SubscriptionMiddleware(bot, channels)) + dp.callback_query.middleware(SubscriptionMiddleware(bot, channels)) + ``` + """ + + def __init__( + self, + bot: Bot, + channels: list[Union[ChannelConfig, str, int]], + cache_ttl: float = 300.0, + whitelist_admins: bool = True, + show_buttons: bool = True, + auto_fetch_links: bool = True + ): + """ + Инициализация middleware. + + Args: + bot: Экземпляр бота + channels: Список каналов (ChannelConfig, ID или username) + cache_ttl: Время жизни кэша в секундах + whitelist_admins: Пропускать администраторов бота + show_buttons: Показывать кнопки подписки + auto_fetch_links: Автоматически получать ссылки на каналы + """ + super().__init__() + self.bot = bot + self.cache = SubscriptionCache(ttl=cache_ttl) + self.whitelist_admins = whitelist_admins + self.show_buttons = show_buttons + self.auto_fetch_links = auto_fetch_links + + # Преобразуем channels в ChannelConfig + self.channels: list[ChannelConfig] = [] + for channel in channels: + if isinstance(channel, ChannelConfig): + self.channels.append(channel) + else: + # Простой ID/username -> ChannelConfig + self.channels.append(ChannelConfig(id=channel)) + + # Кэш информации о каналах + self._channel_info_cache: Dict[Union[str, int], Optional[Chat]] = {} + + async def _get_channel_info(self, channel_id: Union[str, int]) -> Optional[Chat]: + """ + Получает информацию о канале. + + Args: + channel_id: ID или username канала + + Returns: + Chat или None: Информация о канале + """ + if channel_id in self._channel_info_cache: + return self._channel_info_cache[channel_id] + + try: + chat = await self.bot.get_chat(channel_id) + self._channel_info_cache[channel_id] = chat + return chat + except (TelegramBadRequest, TelegramForbiddenError) as e: + logger.error( + f"Не удалось получить информацию о канале {channel_id}: {e}", + log_type='SUBSCRIPTION' + ) + self._channel_info_cache[channel_id] = None + return None + + async def _check_subscription( + self, + user_id: int, + channel_config: ChannelConfig + ) -> bool: + """ + Проверяет подписку пользователя на канал. + + Args: + user_id: ID пользователя + channel_config: Конфигурация канала + + Returns: + bool: True если подписан + """ + channel_id = channel_config.id + + # Проверяем кэш + cached = self.cache.get(user_id, channel_id) + if cached is not None: + logger.debug( + f"Использован кэш для проверки подписки на {channel_id}: {cached}", + log_type='SUBSCRIPTION' + ) + return cached + + # Выполняем проверку + try: + member = await self.bot.get_chat_member( + chat_id=channel_id, + user_id=user_id + ) + + is_subscribed = member.status in ( + ChatMemberStatus.MEMBER, + ChatMemberStatus.ADMINISTRATOR, + ChatMemberStatus.CREATOR + ) + + # Сохраняем в кэш + self.cache.set(user_id, channel_id, is_subscribed) + + logger.debug( + f"Проверка подписки user={user_id} на канал={channel_id}: " + f"{member.status.value} ({'✅' if is_subscribed else '❌'})", + log_type='SUBSCRIPTION' + ) + + return is_subscribed + + except TelegramBadRequest as e: + logger.warning( + f"Канал {channel_id} недоступен или неверный: {e}", + log_type='SUBSCRIPTION' + ) + # В случае ошибки считаем что не подписан + self.cache.set(user_id, channel_id, False) + return False + + except TelegramForbiddenError as e: + logger.error( + f"Бот не имеет доступа к каналу {channel_id}: {e}", + log_type='SUBSCRIPTION' + ) + self.cache.set(user_id, channel_id, False) + return False + + async def _build_subscription_message( + self, + not_subscribed: list[ChannelConfig] + ) -> tuple[str, InlineKeyboardBuilder]: + """ + Создает сообщение и клавиатуру для подписки. + + Args: + not_subscribed: Список каналов без подписки + + Returns: + tuple: (текст_сообщения, клавиатура) + """ + # Текст сообщения + text = "📢 Для использования бота необходимо подписаться на каналы:\n\n" + + # Клавиатура + keyboard = InlineKeyboardBuilder() + + for i, channel_config in enumerate(not_subscribed, 1): + # Получаем информацию о канале + channel_info = await self._get_channel_info(channel_config.id) + + # Определяем название канала + if channel_config.name: + channel_name = channel_config.name + elif channel_info: + channel_name = channel_info.title + else: + channel_name = f"Канал {i}" + + # Добавляем в текст + text += f"{i}. {channel_name}\n" + + # Определяем ссылку + invite_link = channel_config.invite_link + + if not invite_link and self.auto_fetch_links and channel_info: + # Пытаемся получить ссылку + if channel_info.username: + invite_link = f"https://t.me/{channel_info.username}" + elif channel_info.invite_link: + invite_link = channel_info.invite_link + + # Добавляем кнопку если есть ссылка + if invite_link and self.show_buttons: + keyboard.row( + InlineKeyboardButton( + text=f"📌 {channel_name}", + url=invite_link + ) + ) + + text += "\n✅ После подписки нажмите кнопку ниже для проверки." + + # Кнопка проверки подписки + keyboard.row( + InlineKeyboardButton( + text="✅ Я подписался", + callback_data="check_subscription" + ) + ) + + return text, keyboard + + async def __call__( + self, + handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + event: TelegramObject, + data: Dict[str, Any] + ) -> Optional[Any]: + """ + Проверяет подписку перед выполнением хендлера. + + Args: + handler: Функция хендлера + event: Объект события + data: Дополнительные данные + + Returns: + Результат хендлера или None если не подписан + """ + # Пропускаем не-сообщения и не-callback + if not isinstance(event, (Message, CallbackQuery)): + return await handler(event, data) + + # Извлекаем user_id + user_id = event.from_user.id if event.from_user else None + + if user_id is None: + return await handler(event, data) + + user_str = f"@{event.from_user.username}" if event.from_user.username else f"id{user_id}" + + # Whitelist для администраторов + if self.whitelist_admins and user_id in settings.super_admin_ids: + logger.debug( + f"Администратор {user_str} пропущен без проверки подписки", + log_type='SUBSCRIPTION' + ) + return await handler(event, data) + + # Проверяем подписку на все каналы + not_subscribed: list[ChannelConfig] = [] + + for channel_config in self.channels: + # Пропускаем необязательные каналы + if not channel_config.required: + continue + + is_subscribed = await self._check_subscription(user_id, channel_config) + + if not is_subscribed: + not_subscribed.append(channel_config) + + # Если есть каналы без подписки + if not_subscribed: + logger.info( + f"Пользователь не подписан на {len(not_subscribed)} каналов", + log_type='SUBSCRIPTION', + user=user_str + ) + + # Создаем сообщение + text, keyboard = await self._build_subscription_message(not_subscribed) + + # Отправляем сообщение + if isinstance(event, Message): + await event.answer( + text, + reply_markup=keyboard.as_markup(), + parse_mode="HTML" + ) + elif isinstance(event, CallbackQuery): + # Для callback отправляем в чат или редактируем + if event.message: + try: + await event.message.edit_text( + text, + reply_markup=keyboard.as_markup(), + parse_mode="HTML" + ) + except: + await event.message.answer( + text, + reply_markup=keyboard.as_markup(), + parse_mode="HTML" + ) + + await event.answer( + "⚠️ Требуется подписка на каналы", + show_alert=True + ) + + return None + + # Все подписки в порядке + logger.debug( + f"Проверка подписки пройдена", + log_type='SUBSCRIPTION', + user=user_str + ) + + return await handler(event, data) + + def invalidate_cache( + self, + user_id: Optional[int] = None, + channel_id: Optional[Union[str, int]] = None + ) -> None: + """ + Публичный метод для инвалидации кэша. + + Используется при обработке callback "check_subscription". + + Args: + user_id: ID пользователя + channel_id: ID канала + """ + self.cache.invalidate(user_id, channel_id) + + +# ================= HANDLER ДЛЯ ПРОВЕРКИ ПОДПИСКИ ================= + +async def handle_check_subscription( + callback: CallbackQuery, + subscription_middleware: SubscriptionMiddleware +): + """ + Обработчик callback для повторной проверки подписки. + + Example: + ```python + from filters.callback import CallbackStartsWith + from middleware.subscription import handle_check_subscription, subscription_middleware + + @router.callback_query(CallbackStartsWith("check_subscription")) + async def check_sub(callback: CallbackQuery): + await handle_check_subscription(callback, subscription_middleware) + ``` + """ + user_id = callback.from_user.id + + # Инвалидируем кэш для пользователя + subscription_middleware.invalidate_cache(user_id=user_id) + + await callback.answer("🔄 Проверяю подписку...", show_alert=False) + + # Перепроверяем подписку + not_subscribed = [] + + for channel_config in subscription_middleware.channels: + if not channel_config.required: + continue + + is_subscribed = await subscription_middleware._check_subscription( + user_id, + channel_config + ) + + if not is_subscribed: + not_subscribed.append(channel_config) + + if not_subscribed: + # Все еще не подписан + text, keyboard = await subscription_middleware._build_subscription_message(not_subscribed) + + await callback.message.edit_text( + text, + reply_markup=keyboard.as_markup(), + parse_mode="HTML" + ) + + await callback.answer( + f"❌ Вы еще не подписаны на {len(not_subscribed)} каналов", + show_alert=True + ) + else: + # Подписка подтверждена + await callback.message.delete() + await callback.message.answer( + "✅ Подписка подтверждена!\n\n" + "Теперь вы можете пользоваться ботом. Используйте /start", + parse_mode="HTML" + ) + + logger.info( + f"Подписка успешно подтверждена", + log_type='SUBSCRIPTION', + user=f"@{callback.from_user.username}" if callback.from_user.username else f"id{user_id}" + ) diff --git a/bot/middlewares/time_mdw.py b/bot/middlewares/time_mdw.py new file mode 100644 index 0000000..2333c7b --- /dev/null +++ b/bot/middlewares/time_mdw.py @@ -0,0 +1,311 @@ +""" +Middleware для измерения времени выполнения хендлеров +""" +from time import time +from typing import Callable, Awaitable, Any, Dict, Optional +from dataclasses import dataclass +from collections import defaultdict +from datetime import datetime + +from aiogram import BaseMiddleware +from aiogram.types import TelegramObject, Message, CallbackQuery, Update, User + +from middleware.loggers import logger + +__all__ = ('TimingMiddleware', 'TimingStats') + + +@dataclass +class HandlerMetrics: + """Метрики одного хендлера""" + total_calls: int = 0 + total_time: float = 0.0 + min_time: float = float('inf') + max_time: float = 0.0 + last_call: Optional[datetime] = None + + @property + def avg_time(self) -> float: + """Среднее время выполнения""" + return self.total_time / self.total_calls if self.total_calls > 0 else 0.0 + + def update(self, execution_time: float) -> None: + """Обновляет метрики""" + self.total_calls += 1 + self.total_time += execution_time + self.min_time = min(self.min_time, execution_time) + self.max_time = max(self.max_time, execution_time) + self.last_call = datetime.now() + + +class TimingStats: + """ + Глобальная статистика времени выполнения хендлеров. + + Хранит метрики для каждого хендлера и предоставляет методы для анализа. + """ + + def __init__(self): + self.metrics: Dict[str, HandlerMetrics] = defaultdict(HandlerMetrics) + + def record(self, handler_name: str, execution_time: float) -> None: + """ + Записывает время выполнения хендлера. + + Args: + handler_name: Имя хендлера + execution_time: Время выполнения в секундах + """ + self.metrics[handler_name].update(execution_time) + + def get_stats(self, handler_name: Optional[str] = None) -> Dict[str, Any]: + """ + Возвращает статистику по хендлеру или всем хендлерам. + + Args: + handler_name: Имя конкретного хендлера (если None, возвращает все) + + Returns: + Dict с метриками + """ + if handler_name: + metrics = self.metrics.get(handler_name) + if not metrics: + return {} + + return { + 'handler': handler_name, + 'total_calls': metrics.total_calls, + 'avg_time': f"{metrics.avg_time:.3f}s", + 'min_time': f"{metrics.min_time:.3f}s", + 'max_time': f"{metrics.max_time:.3f}s", + 'last_call': metrics.last_call.strftime('%Y-%m-%d %H:%M:%S') if metrics.last_call else None + } + + # Возвращаем статистику по всем хендлерам + return { + name: { + 'total_calls': m.total_calls, + 'avg_time': f"{m.avg_time:.3f}s", + 'min_time': f"{m.min_time:.3f}s", + 'max_time': f"{m.max_time:.3f}s" + } + for name, m in sorted( + self.metrics.items(), + key=lambda x: x[1].avg_time, + reverse=True + ) + } + + def get_slowest(self, limit: int = 10) -> list[tuple[str, float]]: + """ + Возвращает список самых медленных хендлеров. + + Args: + limit: Количество хендлеров в результате + + Returns: + List кортежей (имя_хендлера, среднее_время) + """ + sorted_handlers = sorted( + self.metrics.items(), + key=lambda x: x[1].avg_time, + reverse=True + ) + return [(name, m.avg_time) for name, m in sorted_handlers[:limit]] + + def reset(self, handler_name: Optional[str] = None) -> None: + """ + Сбрасывает статистику. + + Args: + handler_name: Имя хендлера для сброса (если None, сбрасывает все) + """ + if handler_name: + if handler_name in self.metrics: + del self.metrics[handler_name] + else: + self.metrics.clear() + + +# Глобальный экземпляр статистики +timing_stats = TimingStats() + + +class TimingMiddleware(BaseMiddleware): + """ + Middleware для измерения времени выполнения хендлеров. + + Возможности: + - Измерение времени выполнения каждого хендлера + - Автоматическая классификация (быстрый/средний/медленный) + - Сбор статистики + - Логирование медленных хендлеров + - Предупреждения о критически медленных запросах + + Attributes: + slow_threshold: Порог медленного хендлера (сек) + warning_threshold: Порог критически медленного хендлера (сек) + log_all: Логировать все хендлеры (даже быстрые) + collect_stats: Собирать статистику + + Example: + ```python + from middleware.timing import TimingMiddleware, timing_stats + + # Регистрация middleware + dp.message.middleware(TimingMiddleware(slow_threshold=0.5)) + + # Получение статистики + stats = timing_stats.get_slowest(5) + for handler, avg_time in stats: + print(f"{handler}: {avg_time:.3f}s") + ``` + """ + + def __init__( + self, + slow_threshold: float = 1.0, + warning_threshold: float = 3.0, + log_all: bool = False, + collect_stats: bool = True + ): + """ + Инициализация middleware. + + Args: + slow_threshold: Порог медленного хендлера в секундах + warning_threshold: Порог критически медленного хендлера + log_all: Логировать все хендлеры (иначе только медленные) + collect_stats: Собирать статистику выполнения + """ + super().__init__() + self.slow_threshold = slow_threshold + self.warning_threshold = warning_threshold + self.log_all = log_all + self.collect_stats = collect_stats + + @staticmethod + def _extract_user_info(event: TelegramObject) -> str: + """ + Извлекает информацию о пользователе из события. + + Args: + event: Объект события + + Returns: + str: Форматированная строка с информацией о пользователе + """ + user: Optional[User] = None + + # Прямое извлечение из Message/CallbackQuery + if isinstance(event, (Message, CallbackQuery)): + user = getattr(event, 'from_user', None) + + # Извлечение из Update + elif isinstance(event, Update): + for attr in ['message', 'edited_message', 'callback_query', + 'channel_post', 'edited_channel_post', 'inline_query', + 'chosen_inline_result', 'my_chat_member', 'chat_member']: + obj = getattr(event, attr, None) + if obj and hasattr(obj, 'from_user'): + user = obj.from_user + break + + if user: + return f"@{user.username}" if user.username else f"id{user.id}" + + return "@System" + + @staticmethod + def _get_handler_name(handler: Callable) -> str: + """ + Получает имя хендлера для логирования. + + Args: + handler: Функция хендлера + + Returns: + str: Имя хендлера + """ + # Пытаемся получить полное имя с модулем + if hasattr(handler, '__module__') and hasattr(handler, '__name__'): + return f"{handler.__module__}.{handler.__name__}" + elif hasattr(handler, '__name__'): + return handler.__name__ + else: + return str(handler) + + def _classify_speed(self, execution_time: float) -> tuple[str, str]: + """ + Классифицирует скорость выполнения. + + Args: + execution_time: Время выполнения в секундах + + Returns: + tuple: (уровень_лога, тип_лога) + """ + if execution_time >= self.warning_threshold: + return 'ERROR', 'CRITICAL_SLOW' + elif execution_time >= self.slow_threshold: + return 'WARNING', 'SLOW_HANDLER' + elif execution_time >= self.slow_threshold / 2: + return 'INFO', 'MEDIUM_HANDLER' + else: + return 'DEBUG', 'FAST_HANDLER' + + async def __call__( + self, + handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], + event: TelegramObject, + data: Dict[str, Any] + ) -> Any: + """ + Основной метод middleware. + + Args: + handler: Функция хендлера + event: Объект события + data: Дополнительные данные + + Returns: + Результат выполнения хендлера + """ + start_time = time() + handler_name = self._get_handler_name(handler) + user_str = self._extract_user_info(event) + + # Выполняем хендлер + try: + result = await handler(event, data) + return result + + finally: + # Измеряем время + execution_time = time() - start_time + + # Собираем статистику + if self.collect_stats: + timing_stats.record(handler_name, execution_time) + + # Классифицируем скорость + log_level, log_type = self._classify_speed(execution_time) + + # Логируем результат + if self.log_all or execution_time >= self.slow_threshold / 2: + # Формируем сообщение + if execution_time >= self.warning_threshold: + message = f"⚠️ КРИТИЧЕСКИ медленный хендлер '{handler_name}': {execution_time:.3f}с" + elif execution_time >= self.slow_threshold: + message = f"🐌 Медленный хендлер '{handler_name}': {execution_time:.3f}с" + else: + message = f"⏱️ Хендлер '{handler_name}': {execution_time:.3f}с" + + # Логируем + logger.log_entry( + level=log_level, + text=message, + log_type=log_type, + user=user_str + ) diff --git a/bot/special/__init__.py b/bot/special/__init__.py new file mode 100644 index 0000000..054aaf3 --- /dev/null +++ b/bot/special/__init__.py @@ -0,0 +1 @@ +from .text_processing import * diff --git a/bot/special/text_processing.py b/bot/special/text_processing.py new file mode 100644 index 0000000..1bd52c6 --- /dev/null +++ b/bot/special/text_processing.py @@ -0,0 +1,290 @@ +""" +Утилиты для обработки и нормализации текста. +Используется для обнаружения спама и обхода фильтров. + +Pipeline обработки текста: +1. unicode_to_ascii() - замена Unicode-символов +2. normalize_text() - латиница → кириллица, удаление диакритики +3. clean_separators() - удаление разделителей ("г е й" → "гей") +4. get_lemma() - получение нормальной формы слова +""" +import re +import unicodedata +from typing import Set, List +from pymorphy3 import MorphAnalyzer + +from configs.mapping import UNICODE_MAP, LATIN_TO_CYRILLIC, CYRILLIC_NORMALIZE + +__all__ = ( + "unicode_to_ascii", + "normalize_text", + "clean_separators", + "process_text", + "get_lemma", + "get_inflected_forms", + "morph", + "extract_words" +) + +# Глобальный экземпляр морфоанализатора (инициализируется один раз) +morph = MorphAnalyzer() + + +def unicode_to_ascii(text: str) -> str: + """ + Преобразует Unicode-символы в ASCII/кириллические аналоги. + + Args: + text: Текст с Unicode-символами + + Returns: + str: Текст с нормализованными символами + + Examples: + >> unicode_to_ascii("privet") + "привет" + >> unicode_to_ascii("κупиτь") + "купить" + >> unicode_to_ascii("𝐡𝐞𝐥𝐥𝐨") + "нелло" + """ + return ''.join(UNICODE_MAP.get(char, char) for char in text) + + +def normalize_text(text: str) -> str: + """ + Нормализует текст для обхода фильтров: + 1. Удаляет диакритические знаки (é → e, ė → e) + 2. Заменяет латинские буквы на кириллические + 3. Заменяет похожие кириллические буквы (укр/бел) на русские + + Args: + text: Исходный текст + + Returns: + str: Нормализованный текст + + Examples: + >> normalize_text("prívét") + "привет" + >> normalize_text("hеllo") # h - кириллическая + "нелло" + >> normalize_text("Київ") # і → и + "Киев" + """ + # Шаг 1: Удаляем диакритические знаки (акценты) + # NFD разбивает символ на базовый + диакритику + text = unicodedata.normalize('NFD', text) + # Mn = Mark, Nonspacing (диакритические знаки) + text = ''.join(char for char in text if unicodedata.category(char) != 'Mn') + # Возвращаем в NFC (композитная форма) + text = unicodedata.normalize('NFC', text) + + # Шаг 2: Заменяем латинские → кириллица и нормализуем кириллицу + result: List[str] = [] + for char in text: + # Сначала латиница → кириллица + if char in LATIN_TO_CYRILLIC: + result.append(LATIN_TO_CYRILLIC[char]) + # Потом нормализуем кириллицу (укр/бел → рус) + elif char in CYRILLIC_NORMALIZE: + result.append(CYRILLIC_NORMALIZE[char]) + else: + result.append(char) + + return ''.join(result) + + +def clean_separators(text: str) -> str: + """ + Удаляет разделители между буквами для обнаружения обхода через пробелы/символы. + + Args: + text: Исходный текст + + Returns: + str: Текст без разделителей между буквами + + Examples: + >> clean_separators("г е й") + "гей" + >> clean_separators("г.е.й") + "гей" + >> clean_separators("г*е*й") + "гей" + >> clean_separators("к у п и т ь") + "купить" + >> clean_separators("нормальный текст тут") + "нормальный текст тут" + """ + # Удаляем все НЕ буквенно-цифровые символы, кроме пробелов + cleaned: str = re.sub(r'[^\w\s]', '', text, flags=re.UNICODE) + + # Убираем множественные пробелы + cleaned = re.sub(r'\s+', ' ', cleaned) + + # Убираем пробелы между отдельными буквами + # "г е й" → "гей", но "нормальный текст" остаётся + words = cleaned.split() + result: List[str] = [] + temp_chars: List[str] = [] + + for word in words: + if len(word) == 1: + # Одиночный символ - копим + temp_chars.append(word) + else: + # Полное слово - сначала сбрасываем накопленные символы + if temp_chars: + result.append(''.join(temp_chars)) + temp_chars = [] + result.append(word) + + # Не забываем остаток + if temp_chars: + result.append(''.join(temp_chars)) + + return ' '.join(result) + + +def process_text(text: str, remove_spaces: bool = False) -> str: + """ + Полный пайплайн обработки текста для спам-фильтра. + + Args: + text: Исходный текст + remove_spaces: Удалить все пробелы (для проверки part-слов) + + Returns: + str: Обработанный текст в нижнем регистре + + Examples: + >> process_text("Κупи*τь сейчас!") + "купить сейчас" + >> process_text("г е й", remove_spaces=True) + "гей" + """ + # Приводим к нижнему регистру + text = text.casefold() + + # Шаг 1: Unicode → ASCII/кириллица + text = unicode_to_ascii(text) + + # Шаг 2: Нормализация (латиница → кириллица, диакритика) + text = normalize_text(text) + + # Шаг 3: Удаление разделителей + text = clean_separators(text) + + # Опционально: удаляем все пробелы (для part-проверки) + if remove_spaces: + text = re.sub(r'\s+', '', text) + + return text + + +def get_lemma(word: str) -> str: + """ + Получает нормальную форму слова (лемму). + + Args: + word: Слово для анализа + + Returns: + str: Лемма (нормальная форма) + + Examples: + >> get_lemma("купил") + "купить" + >> get_lemma("карты") + "карта" + >> get_lemma("хочется") + "хотеться" + """ + try: + parsed = morph.parse(word)[0] + return parsed.normal_form + except (IndexError, Exception): + return word + + +def get_inflected_forms(base_word: str, limit: int = 50) -> Set[str]: + """ + Получает все словоформы слова через морфологический анализ. + + Args: + base_word: Исходное слово + limit: Максимальное количество форм (для экономии памяти) + + Returns: + Set[str]: Набор всех словоформ (падежи, числа и т.д.) + + Examples: + >> get_inflected_forms("купить") + {'купить', 'куплю', 'купишь', 'купит', ...} + >> get_inflected_forms("карта") + {'карта', 'карты', 'карте', 'карту', ...} + """ + try: + parsed = morph.parse(base_word)[0] + forms: Set[str] = set() + + for form in parsed.lexeme: + if len(forms) >= limit: + break + forms.add(form.normal_form) + forms.add(form.word) + + return forms + except Exception: + return {base_word} + + +def extract_words(text: str) -> List[str]: + """ + Извлекает слова из текста (только буквы). + + Args: + text: Текст для обработки + + Returns: + List[str]: Список слов + + Examples: + >> extract_words("Привет, как дела?") + ['Привет', 'как', 'дела'] + """ + return re.findall(r'\b\w+\b', text, flags=re.UNICODE) + + +def calculate_similarity(text1: str, text2: str) -> float: + """ + Вычисляет схожесть двух текстов (простая метрика). + + Args: + text1: Первый текст + text2: Второй текст + + Returns: + float: Коэффициент схожести (0.0 - 1.0) + + Examples: + >> calculate_similarity("привет", "привет") + 1.0 + >> calculate_similarity("купить", "продать") + 0.0 + """ + processed1 = process_text(text1) + processed2 = process_text(text2) + + if processed1 == processed2: + return 1.0 + + # Levenshtein distance (простой вариант) + len1, len2 = len(processed1), len(processed2) + if len1 == 0 or len2 == 0: + return 0.0 + + # Считаем совпадающие символы + matches = sum(1 for a, b in zip(processed1, processed2) if a == b) + return matches / max(len1, len2) diff --git a/bot/states/__init__.py b/bot/states/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/templates/__init__.py b/bot/templates/__init__.py new file mode 100644 index 0000000..b969334 --- /dev/null +++ b/bot/templates/__init__.py @@ -0,0 +1 @@ +from .message_callback import * diff --git a/bot/templates/message_callback.py b/bot/templates/message_callback.py new file mode 100644 index 0000000..6cba0d7 --- /dev/null +++ b/bot/templates/message_callback.py @@ -0,0 +1,818 @@ +""" +Универсальные шаблоны для отправки сообщений +""" +from typing import Union, Optional, List, Dict, Callable +from pathlib import Path +from contextlib import suppress + +from aiogram import Bot +from aiogram.fsm.context import FSMContext +from aiogram.types import ( + Message, + CallbackQuery, + InlineKeyboardMarkup, + ReplyKeyboardMarkup, + ReplyKeyboardRemove, + FSInputFile, + InputMediaPhoto, + InputMediaVideo, + InputMediaAudio, + InputMediaDocument, + BufferedInputFile +) +from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError +from aiogram.enums import ParseMode, ChatAction + +from middleware.loggers import logger +from ..utils.state_utils import safe_answer_callback +from ..utils.auto_delete import auto_delete_manager + +__all__ = ( + 'msg', + 'msg_photo', + 'msg_video', + 'msg_document', + 'msg_audio', + 'msg_voice', + 'msg_media_group', + 'edit_msg', + 'delete_msg', + 'forward_msg', + 'send_action', + 'markups', + 'MessageTemplate', + 'batch_send' +) + + +class MessageTemplate: + """ + Класс для хранения шаблонов сообщений. + + Example: + ```python + # Создание шаблона + welcome = MessageTemplate( + text="👋 Привет, {name}! Добро пожаловать в {chat}", + parse_mode=ParseMode.HTML + ) + + # Использование + await welcome.send( + message, + name=user.first_name, + chat=chat.title + ) + ``` + """ + + def __init__( + self, + text: str, + parse_mode: Optional[str] = ParseMode.HTML, + disable_web_page_preview: bool = False, + markup: Optional[Union[InlineKeyboardBuilder, InlineKeyboardMarkup]] = None + ): + self.text = text + self.parse_mode = parse_mode + self.disable_web_page_preview = disable_web_page_preview + self.markup = markup + + def format(self, **kwargs) -> str: + """Форматирует текст с подстановкой переменных""" + return self.text.format(**kwargs) + + async def send( + self, + target: Union[Message, CallbackQuery, int], + bot: Optional[Bot] = None, + **format_kwargs + ) -> Optional[Message]: + """ + Отправляет сообщение по шаблону. + + Args: + target: Куда отправить (Message, CallbackQuery или chat_id) + bot: Экземпляр бота (если target это chat_id) + **format_kwargs: Переменные для форматирования + """ + text = self.format(**format_kwargs) + + if isinstance(target, int): + # Отправка по chat_id + if not bot: + raise ValueError("Bot instance required for chat_id") + + return await bot.send_message( + chat_id=target, + text=text, + parse_mode=self.parse_mode, + disable_web_page_preview=self.disable_web_page_preview, + reply_markup=markups(self.markup) + ) + + else: + # Отправка через Message/CallbackQuery + return await msg( + target, + text=text, + parse_mode=self.parse_mode, + disable_web_page_preview=self.disable_web_page_preview, + markup=self.markup + ) + + +# ================= MARKUP UTILS ================= + +def markups( + markup: Union[ + InlineKeyboardBuilder, + ReplyKeyboardBuilder, + InlineKeyboardMarkup, + ReplyKeyboardMarkup, + ReplyKeyboardRemove, + None + ] = None, + resize_keyboard: bool = True, + one_time_keyboard: bool = False +) -> Optional[Union[InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove]]: + """ + Конвертирует builder в готовый markup. + + Args: + markup: Builder или готовая клавиатура + resize_keyboard: Автоматический размер (для ReplyKeyboard) + one_time_keyboard: Скрыть после нажатия (для ReplyKeyboard) + + Returns: + Готовый markup или None + + Example: + >> builder = InlineKeyboardBuilder() + >> builder.button(text="Test", callback_data="test") + >> keyboard = markups(builder) + """ + if markup is None: + return None + + if isinstance(markup, InlineKeyboardBuilder): + return markup.as_markup() + + if isinstance(markup, ReplyKeyboardBuilder): + return markup.as_markup( + resize_keyboard=resize_keyboard, + one_time_keyboard=one_time_keyboard + ) + + if isinstance(markup, (InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove)): + return markup + + return None + + +# ================= TEXT MESSAGES ================= + +async def msg( + update: Union[Message, CallbackQuery], + text: str, + state: Optional[FSMContext] = None, + markup: Union[InlineKeyboardBuilder, InlineKeyboardMarkup, None] = None, + parse_mode: Optional[str] = ParseMode.HTML, + disable_web_page_preview: bool = False, + answer_callback: bool = True, + state_clear: bool = False, + edit_if_possible: bool = True, + delete_previous: bool = False, + auto_delete: Optional[int] = None, + disable_notification: bool = False, + protect_content: bool = False, + show_typing: bool = False, + log: bool = False +) -> Optional[Message]: + """ + Универсальная отправка/редактирование текстового сообщения. + + Args: + update: Message или CallbackQuery + text: Текст сообщения + state: FSM контекст + markup: Клавиатура + parse_mode: Режим парсинга (HTML, Markdown, None) + disable_web_page_preview: Отключить предпросмотр ссылок + answer_callback: Ответить на callback + state_clear: Очистить состояние + edit_if_possible: Попытаться отредактировать (для callback) + delete_previous: Удалить предыдущее сообщение перед отправкой + auto_delete: Автоудаление через N секунд + disable_notification: Без звука + protect_content: Защита от пересылки + show_typing: Показать "печатает" + log: Логировать отправку + + Returns: + Отправленное сообщение + + Example: + >> # Простая отправка + >> await msg(message, "Привет!") + + >> # С клавиатурой и автоудалением + >> builder = InlineKeyboardBuilder() + >> builder.button(text="OK", callback_data="ok") + >> await msg( + ... callback, + ... "Сообщение удалится через 10 секунд", + ... markup=builder, + ... auto_delete=10 + ... ) + """ + # Получаем message объект + message = update.message if isinstance(update, CallbackQuery) else update + + if not message: + logger.warning("Невозможно получить message объект", log_type='MESSAGE') + return None + + # Показываем typing если нужно + if show_typing: + await send_action(message, ChatAction.TYPING) + + # Удаляем предыдущее сообщение если нужно + if delete_previous: + with suppress(TelegramBadRequest, TelegramForbiddenError): + await message.delete() + + keyboard = markups(markup) + + try: + # Попытка редактирования (для callback) + if edit_if_possible and isinstance(update, CallbackQuery): + sent_message = await message.edit_text( + text=text, + reply_markup=keyboard, + parse_mode=parse_mode, + disable_web_page_preview=disable_web_page_preview + ) + + if log: + logger.debug( + f"Сообщение отредактировано: {message.message_id}", + log_type='MESSAGE' + ) + else: + raise TelegramBadRequest + + except (TelegramBadRequest, TelegramForbiddenError): + # Отправка нового сообщения + try: + sent_message = await message.answer( + text=text, + reply_markup=keyboard, + parse_mode=parse_mode, + disable_web_page_preview=disable_web_page_preview, + disable_notification=disable_notification, + protect_content=protect_content + ) + + if log: + logger.debug( + f"Сообщение отправлено: {sent_message.message_id}", + log_type='MESSAGE' + ) + + except Exception as e: + logger.error(f"Ошибка отправки сообщения: {e}", log_type='MESSAGE') + return None + + # Отвечаем на callback + if answer_callback and isinstance(update, CallbackQuery): + await safe_answer_callback(update) + + # Очищаем состояние + if state_clear and state: + await state.clear() + + # Планируем автоудаление + if auto_delete and sent_message: + await auto_delete_manager.schedule( + bot=message.bot, + chat_id=sent_message.chat.id, + message_id=sent_message.message_id, + delay=auto_delete, + reason="template_auto_delete" + ) + + return sent_message + + +# ================= MEDIA MESSAGES ================= + +async def msg_photo( + update: Union[Message, CallbackQuery], + photo: Union[str, Path, FSInputFile, BufferedInputFile], + caption: Optional[str] = None, + state: Optional[FSMContext] = None, + markup: Union[InlineKeyboardBuilder, InlineKeyboardMarkup, None] = None, + parse_mode: Optional[str] = ParseMode.HTML, + answer_callback: bool = True, + state_clear: bool = False, + edit_if_possible: bool = True, + auto_delete: Optional[int] = None, + has_spoiler: bool = False, + log: bool = False +) -> Optional[Message]: + """ + Универсальная отправка/редактирование фото. + + Args: + update: Message или CallbackQuery + photo: Путь к файлу, FSInputFile или BufferedInputFile + caption: Подпись к фото + state: FSM контекст + markup: Клавиатура + parse_mode: Режим парсинга + answer_callback: Ответить на callback + state_clear: Очистить состояние + edit_if_possible: Попытаться отредактировать + auto_delete: Автоудаление через N секунд + has_spoiler: Спойлер + log: Логировать + + Returns: + Отправленное сообщение + + Example: + >> await msg_photo( + ... message, + ... photo="assets/welcome.jpg", + ... caption="Добро пожаловать!", + ... auto_delete=30 + ... ) + """ + message = update.message if isinstance(update, CallbackQuery) else update + + if not message: + return None + + # Конвертируем путь в FSInputFile + if isinstance(photo, (str, Path)): + photo = FSInputFile(photo) + + keyboard = markups(markup) + + try: + # Попытка редактирования медиа + if edit_if_possible and isinstance(update, CallbackQuery): + media = InputMediaPhoto( + media=photo, + caption=caption, + parse_mode=parse_mode, + has_spoiler=has_spoiler + ) + + await message.edit_media( + media=media, + reply_markup=keyboard + ) + + sent_message = message + + if log: + logger.debug("Фото отредактировано", log_type='MESSAGE') + else: + raise TelegramBadRequest + + except (TelegramBadRequest, TelegramForbiddenError): + # Отправка нового фото + try: + sent_message = await message.answer_photo( + photo=photo, + caption=caption, + reply_markup=keyboard, + parse_mode=parse_mode, + has_spoiler=has_spoiler + ) + + if log: + logger.debug("Фото отправлено", log_type='MESSAGE') + + except Exception as e: + logger.error(f"Ошибка отправки фото: {e}", log_type='MESSAGE') + return None + + if answer_callback and isinstance(update, CallbackQuery): + await safe_answer_callback(update) + + if state_clear and state: + await state.clear() + + if auto_delete and sent_message: + await auto_delete_manager.schedule( + bot=message.bot, + chat_id=sent_message.chat.id, + message_id=sent_message.message_id, + delay=auto_delete + ) + + return sent_message + + +async def msg_video( + update: Union[Message, CallbackQuery], + video: Union[str, Path, FSInputFile, BufferedInputFile], + caption: Optional[str] = None, + **kwargs +) -> Optional[Message]: + """ + Отправка видео. + + Поддерживает те же параметры что и msg_photo. + """ + message = update.message if isinstance(update, CallbackQuery) else update + + if not message: + return None + + if isinstance(video, (str, Path)): + video = FSInputFile(video) + + try: + sent = await message.answer_video( + video=video, + caption=caption, + parse_mode=kwargs.get('parse_mode', ParseMode.HTML), + reply_markup=markups(kwargs.get('markup')) + ) + + if kwargs.get('answer_callback') and isinstance(update, CallbackQuery): + await safe_answer_callback(update) + + if kwargs.get('state_clear') and kwargs.get('state'): + await kwargs['state'].clear() + + if kwargs.get('auto_delete'): + await auto_delete_manager.schedule( + bot=message.bot, + chat_id=sent.chat.id, + message_id=sent.message_id, + delay=kwargs['auto_delete'] + ) + + return sent + + except Exception as e: + logger.error(f"Ошибка отправки видео: {e}", log_type='MESSAGE') + return None + + +async def msg_document( + update: Union[Message, CallbackQuery], + document: Union[str, Path, FSInputFile, BufferedInputFile], + caption: Optional[str] = None, + filename: Optional[str] = None, + **kwargs +) -> Optional[Message]: + """ + Отправка документа. + + Args: + filename: Имя файла для отображения + :param filename: + :param caption: + :param document: + :param update: + """ + message = update.message if isinstance(update, CallbackQuery) else update + + if not message: + return None + + if isinstance(document, (str, Path)): + document = FSInputFile(document, filename=filename) + + try: + sent = await message.answer_document( + document=document, + caption=caption, + parse_mode=kwargs.get('parse_mode', ParseMode.HTML), + reply_markup=markups(kwargs.get('markup')) + ) + + if kwargs.get('answer_callback') and isinstance(update, CallbackQuery): + await safe_answer_callback(update) + + if kwargs.get('state_clear') and kwargs.get('state'): + await kwargs['state'].clear() + + if kwargs.get('auto_delete'): + await auto_delete_manager.schedule( + bot=message.bot, + chat_id=sent.chat.id, + message_id=sent.message_id, + delay=kwargs['auto_delete'] + ) + + return sent + + except Exception as e: + logger.error(f"Ошибка отправки документа: {e}", log_type='MESSAGE') + return None + + +async def msg_audio( + update: Union[Message, CallbackQuery], + audio: Union[str, Path, FSInputFile, BufferedInputFile], + caption: Optional[str] = None, + **kwargs +) -> Optional[Message]: + """Отправка аудио""" + message = update.message if isinstance(update, CallbackQuery) else update + + if not message: + return None + + if isinstance(audio, (str, Path)): + audio = FSInputFile(audio) + + try: + return await message.answer_audio( + audio=audio, + caption=caption, + parse_mode=kwargs.get('parse_mode', ParseMode.HTML), + reply_markup=markups(kwargs.get('markup')) + ) + except Exception as e: + logger.error(f"Ошибка отправки аудио: {e}", log_type='MESSAGE') + return None + + +async def msg_voice( + update: Union[Message, CallbackQuery], + voice: Union[str, Path, FSInputFile, BufferedInputFile], + caption: Optional[str] = None, + **kwargs +) -> Optional[Message]: + """Отправка голосового сообщения""" + message = update.message if isinstance(update, CallbackQuery) else update + + if not message: + return None + + if isinstance(voice, (str, Path)): + voice = FSInputFile(voice) + + try: + return await message.answer_voice( + voice=voice, + caption=caption, + parse_mode=kwargs.get('parse_mode', ParseMode.HTML), + reply_markup=markups(kwargs.get('markup')) + ) + except Exception as e: + logger.error(f"Ошибка отправки голосового: {e}", log_type='MESSAGE') + return None + + +async def msg_media_group( + message: Message, + media: List[Union[InputMediaPhoto, InputMediaVideo, InputMediaAudio, InputMediaDocument]], + caption: Optional[str] = None +) -> Optional[List[Message]]: + """ + Отправка media group (альбом). + + Args: + message: Объект сообщения + media: Список медиа + caption: Подпись (будет добавлена к первому элементу) + + Returns: + Список отправленных сообщений + + Example: + >> media = [ + ... InputMediaPhoto(media=FSInputFile("photo1.jpg")), + ... InputMediaPhoto(media=FSInputFile("photo2.jpg")), + ... InputMediaVideo(media=FSInputFile("video.mp4")) + ... ] + >> await msg_media_group(message, media, caption="Альбом") + """ + if not media: + return None + + # Добавляем подпись к первому элементу + if caption and media: + media[0].caption = caption + + try: + return await message.answer_media_group(media=media) + except Exception as e: + logger.error(f"Ошибка отправки media group: {e}", log_type='MESSAGE') + return None + + +# ================= MESSAGE ACTIONS ================= + +async def edit_msg( + message: Message, + text: Optional[str] = None, + caption: Optional[str] = None, + markup: Optional[InlineKeyboardMarkup] = None, + parse_mode: Optional[str] = ParseMode.HTML +) -> bool: + """ + Безопасное редактирование сообщения. + + Returns: + bool: True если успешно отредактировано + """ + try: + if text: + await message.edit_text( + text=text, + reply_markup=markup, + parse_mode=parse_mode + ) + elif caption: + await message.edit_caption( + caption=caption, + reply_markup=markup, + parse_mode=parse_mode + ) + else: + await message.edit_reply_markup(reply_markup=markup) + + return True + + except (TelegramBadRequest, TelegramForbiddenError) as e: + logger.debug(f"Не удалось отредактировать сообщение: {e}", log_type='MESSAGE') + return False + + +async def delete_msg( + message: Message, + delay: Optional[int] = None +) -> bool: + """ + Безопасное удаление сообщения. + + Args: + message: Сообщение для удаления + delay: Задержка перед удалением (секунды) + + Returns: + bool: True если успешно удалено + """ + if delay: + await auto_delete_manager.schedule( + bot=message.bot, + chat_id=message.chat.id, + message_id=message.message_id, + delay=delay + ) + return True + + try: + await message.delete() + return True + except (TelegramBadRequest, TelegramForbiddenError): + return False + + +async def forward_msg( + message: Message, + to_chat_id: int, + disable_notification: bool = False, + protect_content: bool = False +) -> Optional[Message]: + """ + Пересылка сообщения. + + Args: + message: Исходное сообщение + to_chat_id: ID чата куда переслать + disable_notification: Без звука + protect_content: Защита от пересылки + + Returns: + Пересланное сообщение + """ + try: + return await message.forward( + chat_id=to_chat_id, + disable_notification=disable_notification, + protect_content=protect_content + ) + except Exception as e: + logger.error(f"Ошибка пересылки сообщения: {e}", log_type='MESSAGE') + return None + + +async def send_action( + message: Message, + action: ChatAction = ChatAction.TYPING +) -> bool: + """ + Отправка chat action (печатает, загружает фото и т.д.). + + Args: + message: Объект сообщения + action: Тип действия + + Returns: + bool: True если успешно + + Example: + >> await send_action(message, ChatAction.TYPING) + >> await send_action(message, ChatAction.UPLOAD_PHOTO) + """ + try: + await message.bot.send_chat_action( + chat_id=message.chat.id, + action=action + ) + return True + except: + return False + + +# ================= BATCH SENDING ================= + +async def batch_send( + bot: Bot, + chat_ids: List[int], + text: str, + markup: Optional[InlineKeyboardMarkup] = None, + parse_mode: Optional[str] = ParseMode.HTML, + disable_notification: bool = False, + on_success: Optional[Callable] = None, + on_error: Optional[Callable] = None +) -> Dict[str, int]: + """ + Массовая рассылка сообщений. + + Args: + bot: Экземпляр бота + chat_ids: Список ID чатов + text: Текст сообщения + markup: Клавиатура + parse_mode: Режим парсинга + disable_notification: Без звука + on_success: Callback при успехе (chat_id) + on_error: Callback при ошибке (chat_id, error) + + Returns: + Dict со статистикой: {'success': N, 'failed': N} + + Example: + >> stats = await batch_send( + ... bot, + ... [123, 456, 789], + ... "Важное объявление!" + ... ) + >> print(f"Отправлено: {stats['success']}") + """ + import asyncio + + success_count = 0 + failed_count = 0 + + for chat_id in chat_ids: + try: + await bot.send_message( + chat_id=chat_id, + text=text, + reply_markup=markup, + parse_mode=parse_mode, + disable_notification=disable_notification + ) + + success_count += 1 + + if on_success: + await on_success(chat_id) + + except Exception as e: + failed_count += 1 + + if on_error: + await on_error(chat_id, e) + + logger.warning( + f"Не удалось отправить сообщение в чат {chat_id}: {e}", + log_type='BATCH' + ) + + # Небольшая задержка чтобы избежать rate limit + await asyncio.sleep(0.05) + + logger.info( + f"Рассылка завершена: успешно={success_count}, ошибок={failed_count}", + log_type='BATCH' + ) + + return { + 'success': success_count, + 'failed': failed_count + } diff --git a/bot/utils/__init__.py b/bot/utils/__init__.py new file mode 100644 index 0000000..bfe2697 --- /dev/null +++ b/bot/utils/__init__.py @@ -0,0 +1,38 @@ +""" +Утилиты бота PrimoGuardBot + +Модули: +- usernames: Работа с пользователями (username, mentions, display names) +- type_message: Типы контента и чатов +- hidden_username: Упоминания администраторов +- format_time: Форматирование времени и дат +- argument: Парсинг команд и аргументов +- state_utils: Работа с FSM состояниями +- auto_delete: Автоматическое удаление сообщений +- decorators: Декораторы для хендлеров +""" + +# ================= USER INFO ================= +from .usernames import * + +# ================= CONTENT TYPES ================= +from .type_message import * + +# ================= MENTIONS ================= +from .hidden_username import * + +# ================= TIME FORMATTING ================= +from .format_time import * + +# ================= COMMANDS ================= +from .argument import * + +# ================= STATE UTILS ================= +from .state_utils import * + +# ================= AUTO DELETE ================= +from .auto_delete import * + +# ================= DECORATORS ================= +from .decorators import * + diff --git a/bot/utils/argument.py b/bot/utils/argument.py new file mode 100644 index 0000000..d2871ec --- /dev/null +++ b/bot/utils/argument.py @@ -0,0 +1,688 @@ +""" +Утилиты для работы с командами бота +""" +from typing import Optional, Union, Dict, List, Tuple, Set +from dataclasses import dataclass, field +import re + +from aiogram.types import Message + +from configs import settings + +__all__ = ( + 'is_command', + 'find_argument', + 'get_command', + 'parse_arguments', + 'parse_flags', + 'CommandParser', + 'ParsedCommand', + 'parse_command', + 'validate_command', + 'get_command_usage', + 'extract_mentions', + 'extract_user_ids', + 'extract_hashtags' +) + + +@dataclass +class ParsedCommand: + """ + Распарсенная команда. + + Attributes: + command: Название команды + prefix: Префикс команды + args: Список аргументов + raw_args: Исходная строка аргументов + flags: Словарь флагов (--flag value) + bot_username: Username бота (если было упоминание) + is_group_command: Команда в группе с упоминанием бота + """ + command: str + prefix: str + args: List[str] = field(default_factory=list) + raw_args: Optional[str] = None + flags: Dict[str, Union[str, bool]] = field(default_factory=dict) + bot_username: Optional[str] = None + is_group_command: bool = False + + @property + def has_args(self) -> bool: + """Есть ли аргументы""" + return len(self.args) > 0 + + @property + def has_flags(self) -> bool: + """Есть ли флаги""" + return len(self.flags) > 0 + + def get_arg(self, index: int, default: Optional[str] = None) -> Optional[str]: + """Получает аргумент по индексу""" + return self.args[index] if index < len(self.args) else default + + def get_flag(self, name: str, default: Optional[Union[str, bool]] = None) -> Union[str, bool, None]: + """Получает значение флага""" + return self.flags.get(name, default) + + def __repr__(self) -> str: + return ( + f"ParsedCommand(command='{self.command}', " + f"args={self.args}, flags={self.flags})" + ) + + +class CommandParser: + """ + Парсер команд бота. + + Возможности: + - Поддержка нескольких префиксов + - Парсинг аргументов + - Парсинг флагов (--flag value, -f value) + - Поддержка упоминаний бота (@botname) + - Парсинг quoted аргументов ("arg with spaces") + - Валидация команд + + Example: + ```python + parser = CommandParser() + + # Парсинг команды + parsed = parser.parse("/ban @user 7d --reason спам") + print(parsed.command) # "ban" + print(parsed.args) # ["@user", "7d"] + print(parsed.flags) # {"reason": "спам"} + ``` + """ + + def __init__( + self, + prefixes: Optional[List[str]] = None, + bot_username: Optional[str] = None + ): + """ + Args: + prefixes: Список префиксов (по умолчанию из settings) + bot_username: Username бота для проверки упоминаний + """ + self.prefixes = prefixes or settings.PREFIX + self.bot_username = bot_username + + def is_command(self, text: Optional[str]) -> bool: + """ + Проверяет, является ли текст командой. + + Args: + text: Текст для проверки + + Returns: + bool: True если это команда + + Example: + >> parser.is_command("/start") + True + >> parser.is_command("hello") + False + """ + if not text: + return False + + text = text.strip() + + # Проверяем все префиксы + return any(text.startswith(prefix) for prefix in self.prefixes) + + def get_command( + self, + text: Optional[str], + strip_mention: bool = True + ) -> Optional[str]: + """ + Извлекает название команды из текста. + + Args: + text: Текст сообщения + strip_mention: Убирать упоминание бота (@botname) + + Returns: + Optional[str]: Название команды или None + + Example: + >> parser.get_command("/start@mybot arg") + 'start' + >> parser.get_command("!help") + 'help' + """ + if not self.is_command(text): + return None + + text = text.strip() + + # Находим префикс + prefix = next(p for p in self.prefixes if text.startswith(p)) + + # Убираем префикс + without_prefix = text[len(prefix):] + + # Берем первое слово + command = without_prefix.split()[0] if without_prefix else "" + + # Убираем упоминание бота если есть + if strip_mention and '@' in command: + command = command.split('@')[0] + + return command.lower() if command else None + + def find_argument(self, text: Optional[str]) -> Optional[str]: + """ + Извлекает аргументы команды (все после команды). + + Args: + text: Текст сообщения + + Returns: + Optional[str]: Аргументы или None + + Example: + >> parser.find_argument("/start referrer") + 'referrer' + >> parser.find_argument("/ban @user reason text") + '@user reason text' + """ + if not self.is_command(text): + return None + + parts = text.strip().split(maxsplit=1) + return parts[1] if len(parts) > 1 else None + + @staticmethod + def parse_arguments( + args_text: Optional[str], + preserve_quotes: bool = False + ) -> List[str]: + """ + Парсит аргументы, поддерживает кавычки. + + Args: + args_text: Строка аргументов + preserve_quotes: Сохранять кавычки в результате + + Returns: + List[str]: Список аргументов + + Example: + >> parser.parse_arguments('user 7d "ban reason here"') + ['user', '7d', 'ban reason here'] + """ + if not args_text: + return [] + + # Regex для парсинга с кавычками + # Поддерживает: "arg with spaces" 'arg' arg + pattern = r'''(?:[^\s"']+|"[^"]*"|'[^']*')+''' + matches = re.findall(pattern, args_text) + + if preserve_quotes: + return matches + + # Убираем кавычки + return [m.strip('"').strip("'") for m in matches] + + @staticmethod + def parse_flags( + args: List[str] + ) -> Tuple[List[str], Dict[str, Union[str, bool]]]: + """ + Парсит флаги из аргументов. + + Поддерживает: + - --flag value + - --flag (boolean, True) + - -f value (короткая форма) + + Args: + args: Список аргументов + + Returns: + Tuple: (аргументы_без_флагов, словарь_флагов) + + Example: + >> args = ['user', '--reason', 'spam', '--silent'] + >> clean_args, flags = parser.parse_flags(args) + >> print(clean_args) # ['user'] + >> print(flags) # {'reason': 'spam', 'silent': True} + """ + clean_args = [] + flags = {} + + i = 0 + while i < len(args): + arg = args[i] + + # Длинный флаг --flag + if arg.startswith('--'): + flag_name = arg[2:] + + # Проверяем, есть ли значение + if i + 1 < len(args) and not args[i + 1].startswith('-'): + flags[flag_name] = args[i + 1] + i += 2 + else: + # Boolean флаг + flags[flag_name] = True + i += 1 + + # Короткий флаг -f + elif arg.startswith('-') and len(arg) == 2: + flag_name = arg[1] + + # Проверяем значение + if i + 1 < len(args) and not args[i + 1].startswith('-'): + flags[flag_name] = args[i + 1] + i += 2 + else: + flags[flag_name] = True + i += 1 + + # Обычный аргумент + else: + clean_args.append(arg) + i += 1 + + return clean_args, flags + + def parse( + self, + text: str, + parse_flags: bool = True + ) -> Optional[ParsedCommand]: + """ + Полный парсинг команды. + + Args: + text: Текст команды + parse_flags: Парсить флаги + + Returns: + Optional[ParsedCommand]: Распарсенная команда или None + + Example: + >> parsed = parser.parse('/ban @user 7d --reason "spam bot"') + >> print(parsed.command) # 'ban' + >> print(parsed.args) # ['@user', '7d'] + >> print(parsed.flags) # {'reason': 'spam bot'} + """ + if not self.is_command(text): + return None + + text = text.strip() + + # Находим префикс + prefix = next(p for p in self.prefixes if text.startswith(p)) + + # Убираем префикс + without_prefix = text[len(prefix):] + + # Разделяем на команду и аргументы + parts = without_prefix.split(maxsplit=1) + if not parts: + return None + + command_part = parts[0] + raw_args = parts[1] if len(parts) > 1 else None + + # Проверяем упоминание бота + bot_username = None + is_group_command = False + + if '@' in command_part: + cmd_parts = command_part.split('@') + command_name = cmd_parts[0] + bot_username = cmd_parts[1] if len(cmd_parts) > 1 else None + is_group_command = True + else: + command_name = command_part + + # Парсим аргументы + args = self.parse_arguments(raw_args) if raw_args else [] + + # Парсим флаги + flags = {} + if parse_flags and args: + args, flags = self.parse_flags(args) + + return ParsedCommand( + command=command_name.lower(), + prefix=prefix, + args=args, + raw_args=raw_args, + flags=flags, + bot_username=bot_username, + is_group_command=is_group_command + ) + + def parse_from_message( + self, + message: Message, + parse_flags: bool = True + ) -> Optional[ParsedCommand]: + """ + Парсит команду из объекта Message. + + Args: + message: Объект сообщения + parse_flags: Парсить флаги + + Returns: + Optional[ParsedCommand]: Распарсенная команда + + Example: + >> parsed = parser.parse_from_message(message) + >> if parsed: + ... print(f"Команда: {parsed.command}") + """ + if not message.text: + return None + + return self.parse(message.text, parse_flags=parse_flags) + + +# Глобальный парсер +_default_parser: Optional[CommandParser] = None + + +def get_parser() -> CommandParser: + """Получает глобальный парсер команд""" + global _default_parser + if _default_parser is None: + _default_parser = CommandParser() + return _default_parser + + +# ================= УДОБНЫЕ ФУНКЦИИ ================= + +def is_command(text: Optional[str]) -> bool: + """ + Проверяет, является ли текст командой. + + Args: + text: Текст для проверки + + Returns: + bool: True если это команда + + Example: + >> is_command("/start") + True + >> is_command("hello") + False + """ + return get_parser().is_command(text) + + +def find_argument(text: Optional[str]) -> Optional[str]: + """ + Извлекает аргументы команды. + + Args: + text: Текст команды + + Returns: + Optional[str]: Аргументы или None + + Example: + >> find_argument("/start referrer") + 'referrer' + >> find_argument("/ban @user spam") + '@user spam' + """ + return get_parser().find_argument(text) + + +def get_command(text: Optional[str]) -> Optional[str]: + """ + Извлекает название команды. + + Args: + text: Текст сообщения + + Returns: + Optional[str]: Название команды или None + + Example: + >> get_command("/start@mybot") + 'start' + >> get_command("!help") + 'help' + """ + return get_parser().get_command(text) + + +def parse_arguments(args_text: Optional[str]) -> List[str]: + """ + Парсит аргументы команды. + + Args: + args_text: Строка аргументов + + Returns: + List[str]: Список аргументов + + Example: + >> parse_arguments('user 7d "ban reason"') + ['user', '7d', 'ban reason'] + """ + return get_parser().parse_arguments(args_text) + + +def parse_flags(args: List[str]) -> Tuple[List[str], Dict[str, Union[str, bool]]]: + """ + Парсит флаги из аргументов. + + Args: + args: Список аргументов + + Returns: + Tuple: (аргументы, флаги) + + Example: + >> args = ['user', '--reason', 'spam', '--silent'] + >> clean_args, flags = parse_flags(args) + >> print(flags) # {'reason': 'spam', 'silent': True} + """ + return get_parser().parse_flags(args) + + +def parse_command(text: str) -> Optional[ParsedCommand]: + """ + Полный парсинг команды. + + Args: + text: Текст команды + + Returns: + Optional[ParsedCommand]: Распарсенная команда + + Example: + >> parsed = parse_command('/ban @user --reason spam') + >> print(parsed.command) # 'ban' + >> print(parsed.args) # ['@user'] + >> print(parsed.flags) # {'reason': 'spam'} + """ + return get_parser().parse(text) + + +# ================= ВАЛИДАЦИЯ КОМАНД ================= + +def validate_command( + text: str, + expected_command: str, + min_args: int = 0, + max_args: Optional[int] = None, + required_flags: Optional[Set[str]] = None +) -> Tuple[bool, Optional[str]]: + """ + Валидирует команду. + + Args: + text: Текст команды + expected_command: Ожидаемая команда + min_args: Минимальное количество аргументов + max_args: Максимальное количество аргументов + required_flags: Обязательные флаги + + Returns: + Tuple[bool, Optional[str]]: (валидна, сообщение_об_ошибке) + + Example: + >> valid, error = validate_command( + ... '/ban user', + ... 'ban', + ... min_args=1, + ... max_args=2 + ... ) + >> if not valid: + ... print(error) + """ + parsed = parse_command(text) + + if not parsed: + return False, "Невалидная команда" + + # Проверка команды + if parsed.command != expected_command: + return False, f"Ожидалась команда '{expected_command}'" + + # Проверка количества аргументов + arg_count = len(parsed.args) + + if arg_count < min_args: + return False, f"Недостаточно аргументов (минимум {min_args})" + + if max_args is not None and arg_count > max_args: + return False, f"Слишком много аргументов (максимум {max_args})" + + # Проверка обязательных флагов + if required_flags: + missing_flags = required_flags - set(parsed.flags.keys()) + if missing_flags: + return False, f"Отсутствуют обязательные флаги: {', '.join(missing_flags)}" + + return True, None + + +def get_command_usage( + command: str, + args: List[str], + flags: Optional[Dict[str, str]] = None, + description: Optional[str] = None +) -> str: + """ + Формирует строку использования команды. + + Args: + command: Название команды + args: Список аргументов + flags: Словарь флагов с описанием + description: Описание команды + + Returns: + str: Форматированная строка использования + + Example: + >> usage = get_command_usage( + ... 'ban', + ... ['', '[duration]'], + ... {'reason': 'Причина бана', 'silent': 'Тихий бан'}, + ... 'Банит пользователя' + ... ) + >> print(usage) + """ + lines = [] + + # Описание + if description: + lines.append(f"📝 {description}\n") + + # Использование + args_str = ' '.join(args) + lines.append(f"Использование:") + lines.append(f"/{command} {args_str}\n") + + # Аргументы + if args: + lines.append("Аргументы:") + for arg in args: + # Определяем обязательность + if arg.startswith('<') and arg.endswith('>'): + lines.append(f"• {arg} - обязательный") + elif arg.startswith('[') and arg.endswith(']'): + lines.append(f"• {arg} - необязательный") + lines.append("") + + # Флаги + if flags: + lines.append("Флаги:") + for flag, desc in flags.items(): + lines.append(f"• --{flag} - {desc}") + + return '\n'.join(lines) + + +# ================= ИЗВЛЕЧЕНИЕ УПОМИНАНИЙ ================= + +def extract_mentions(text: str) -> List[str]: + """ + Извлекает все упоминания (@username) из текста. + + Args: + text: Текст для анализа + + Returns: + List[str]: Список username (без @) + + Example: + >> extract_mentions("Бан @user1 и @user2") + ['user1', 'user2'] + """ + pattern = r'@(\w+)' + return re.findall(pattern, text) + + +def extract_user_ids(text: str) -> List[int]: + """ + Извлекает все ID пользователей из текста. + + Args: + text: Текст для анализа + + Returns: + List[int]: Список ID + + Example: + >> extract_user_ids("Бан id123456789 и id987654321") + [123456789, 987654321] + """ + pattern = r'id(\d+)' + matches = re.findall(pattern, text) + return [int(m) for m in matches] + + +def extract_hashtags(text: str) -> List[str]: + """ + Извлекает все хештеги из текста. + + Args: + text: Текст для анализа + + Returns: + List[str]: Список хештегов (без #) + + Example: + >> extract_hashtags("Пост #важное #новости") + ['важное', 'новости'] + """ + pattern = r'#(\w+)' + return re.findall(pattern, text) diff --git a/bot/utils/auto_delete.py b/bot/utils/auto_delete.py new file mode 100644 index 0000000..300d060 --- /dev/null +++ b/bot/utils/auto_delete.py @@ -0,0 +1,636 @@ +""" +Утилиты для автоматического удаления сообщений +""" +from typing import Optional, Callable, Awaitable, Dict, Any +from dataclasses import dataclass, field +from datetime import datetime, timedelta +from asyncio import sleep, create_task, Task, CancelledError + +from aiogram import Bot +from aiogram.types import Message +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError + +from middleware.loggers import logger +from .format_time import format_duration + +__all__ = ( + 'auto_delete_message', + 'schedule_delete', + 'cancel_delete', + 'delete_after', + 'auto_delete_manager', + 'AutoDeleteManager', + 'DeleteTask', + 'delete_both_after', + 'delete_messages_after', +) + + +@dataclass +class DeleteTask: + """ + Задача на удаление сообщения. + + Attributes: + chat_id: ID чата + message_id: ID сообщения + delete_at: Время удаления + task: Asyncio task + created_at: Время создания задачи + reason: Причина удаления + callback: Callback функция после удаления + """ + chat_id: int + message_id: int + delete_at: datetime + task: Optional[Task] = None + created_at: datetime = field(default_factory=datetime.now) + reason: Optional[str] = None + callback: Optional[Callable[[], Awaitable[None]]] = None + + @property + def delay(self) -> int: + """Задержка до удаления в секундах""" + delta = self.delete_at - datetime.now() + return max(0, int(delta.total_seconds())) + + @property + def is_expired(self) -> bool: + """Истекло ли время удаления""" + return datetime.now() >= self.delete_at + + def __repr__(self) -> str: + return ( + f"DeleteTask(chat={self.chat_id}, msg={self.message_id}, " + f"delay={self.delay}s, reason={self.reason})" + ) + + +class AutoDeleteManager: + """ + Менеджер автоматического удаления сообщений. + + Возможности: + - Планирование удаления с задержкой + - Отмена запланированного удаления + - Массовое удаление + - Callback функции + - История задач + - Автоматическая очистка завершенных задач + + Example: + ```python + from utils.auto_delete import auto_delete_manager + + # Планирование удаления + await auto_delete_manager.schedule( + bot=bot, + chat_id=message.chat.id, + message_id=message.message_id, + delay=60, + reason="Временное сообщение" + ) + + # Отмена удаления + auto_delete_manager.cancel(message.chat.id, message.message_id) + + # Получение статистики + stats = auto_delete_manager.get_stats() + ``` + """ + + def __init__(self): + # Активные задачи: {(chat_id, message_id): DeleteTask} + self.tasks: Dict[tuple[int, int], DeleteTask] = {} + + # Завершенные задачи (последние 100) + self.completed: list[DeleteTask] = [] + self.max_completed = 100 + + # Статистика + self.total_scheduled: int = 0 + self.total_deleted: int = 0 + self.total_failed: int = 0 + self.total_cancelled: int = 0 + + async def schedule( + self, + bot: Bot, + chat_id: int, + message_id: int, + delay: int, + reason: Optional[str] = None, + callback: Optional[Callable[[], Awaitable[None]]] = None, + log: bool = True + ) -> DeleteTask: + """ + Планирует удаление сообщения. + + Args: + bot: Экземпляр бота + chat_id: ID чата + message_id: ID сообщения + delay: Задержка в секундах + reason: Причина удаления + callback: Callback функция после удаления + log: Логировать планирование + + Returns: + DeleteTask: Созданная задача + + Example: + >> task = await auto_delete_manager.schedule( + ... bot=bot, + ... chat_id=message.chat.id, + ... message_id=message.message_id, + ... delay=60, + ... reason="Спам" + ... ) + """ + # Отменяем предыдущую задачу если есть + key = (chat_id, message_id) + if key in self.tasks: + self.cancel(chat_id, message_id) + + # Создаем задачу + delete_at = datetime.now() + timedelta(seconds=delay) + task_data = DeleteTask( + chat_id=chat_id, + message_id=message_id, + delete_at=delete_at, + reason=reason, + callback=callback + ) + + # Создаем asyncio task + task = create_task(self._delete_task(bot, task_data, log)) + task_data.task = task + + # Сохраняем + self.tasks[key] = task_data + self.total_scheduled += 1 + + if log: + delay_str = format_duration(delay) + logger.info( + f"Запланировано удаление сообщения через {delay_str}", + log_type='AUTO_DELETE' + ) + + return task_data + + async def _delete_task( + self, + bot: Bot, + task_data: DeleteTask, + log: bool + ) -> None: + """ + Внутренняя функция для выполнения задачи удаления. + + Args: + bot: Экземпляр бота + task_data: Данные задачи + log: Логировать выполнение + """ + key = (task_data.chat_id, task_data.message_id) + + try: + # Ждем + await sleep(task_data.delay) + + # Удаляем сообщение + await bot.delete_message( + chat_id=task_data.chat_id, + message_id=task_data.message_id + ) + + self.total_deleted += 1 + + if log: + reason_str = f" (причина: {task_data.reason})" if task_data.reason else "" + logger.info( + f"Сообщение удалено автоматически{reason_str}", + log_type='AUTO_DELETE' + ) + + # Вызываем callback если есть + if task_data.callback: + try: + await task_data.callback() + except Exception as e: + logger.error( + f"Ошибка в callback автоудаления: {e}", + log_type='AUTO_DELETE' + ) + + except CancelledError: + # Задача отменена + self.total_cancelled += 1 + + if log: + logger.debug( + f"Удаление сообщения отменено", + log_type='AUTO_DELETE' + ) + raise + + except (TelegramBadRequest, TelegramForbiddenError) as e: + # Ошибка удаления + self.total_failed += 1 + + if log: + logger.warning( + f"Не удалось автоматически удалить сообщение: {e}", + log_type='AUTO_DELETE' + ) + + finally: + # Удаляем из активных задач + if key in self.tasks: + completed_task = self.tasks.pop(key) + + # Сохраняем в завершенные + self.completed.append(completed_task) + if len(self.completed) > self.max_completed: + self.completed.pop(0) + + def cancel( + self, + chat_id: int, + message_id: int, + log: bool = True + ) -> bool: + """ + Отменяет запланированное удаление. + + Args: + chat_id: ID чата + message_id: ID сообщения + log: Логировать отмену + + Returns: + bool: True если задача была отменена + + Example: + >> cancelled = auto_delete_manager.cancel( + ... chat_id=message.chat.id, + ... message_id=message.message_id + ... ) + """ + key = (chat_id, message_id) + + if key in self.tasks: + task_data = self.tasks[key] + + # Отменяем asyncio task + if task_data.task and not task_data.task.done(): + task_data.task.cancel() + + # Удаляем из активных + self.tasks.pop(key) + + if log: + logger.debug( + f"Автоудаление отменено для сообщения {message_id}", + log_type='AUTO_DELETE' + ) + + return True + + return False + + def cancel_all(self, chat_id: Optional[int] = None) -> int: + """ + Отменяет все запланированные удаления. + + Args: + chat_id: ID чата (если None, отменяет для всех чатов) + + Returns: + int: Количество отмененных задач + + Example: + >> # Отменить для всех чатов + >> count = auto_delete_manager.cancel_all() + + >> # Отменить для конкретного чата + >> count = auto_delete_manager.cancel_all(chat_id=message.chat.id) + """ + cancelled_count = 0 + + # Собираем ключи для отмены + keys_to_cancel = [] + for key, task_data in self.tasks.items(): + if chat_id is None or task_data.chat_id == chat_id: + keys_to_cancel.append(key) + + # Отменяем + for key in keys_to_cancel: + if self.cancel(key[0], key[1], log=False): + cancelled_count += 1 + + if cancelled_count > 0: + logger.info( + f"Отменено {cancelled_count} задач автоудаления", + log_type='AUTO_DELETE' + ) + + return cancelled_count + + def get_task( + self, + chat_id: int, + message_id: int + ) -> Optional[DeleteTask]: + """ + Получает задачу по ID чата и сообщения. + + Args: + chat_id: ID чата + message_id: ID сообщения + + Returns: + Optional[DeleteTask]: Задача или None + """ + key = (chat_id, message_id) + return self.tasks.get(key) + + def get_chat_tasks(self, chat_id: int) -> list[DeleteTask]: + """ + Получает все задачи для чата. + + Args: + chat_id: ID чата + + Returns: + list[DeleteTask]: Список задач + """ + return [ + task for task in self.tasks.values() + if task.chat_id == chat_id + ] + + def get_stats(self) -> Dict[str, Any]: + """ + Возвращает статистику менеджера. + + Returns: + Dict: Словарь со статистикой + + Example: + >> stats = auto_delete_manager.get_stats() + >> print(f"Активных задач: {stats['active_tasks']}") + """ + return { + 'active_tasks': len(self.tasks), + 'completed_tasks': len(self.completed), + 'total_scheduled': self.total_scheduled, + 'total_deleted': self.total_deleted, + 'total_failed': self.total_failed, + 'total_cancelled': self.total_cancelled, + 'success_rate': ( + f"{(self.total_deleted / self.total_scheduled * 100):.1f}%" + if self.total_scheduled > 0 else "0%" + ) + } + + def cleanup_expired(self) -> int: + """ + Удаляет истекшие задачи (которые должны были выполниться, но не выполнились). + + Returns: + int: Количество удаленных задач + """ + expired_keys = [ + key for key, task in self.tasks.items() + if task.is_expired and (not task.task or task.task.done()) + ] + + for key in expired_keys: + self.tasks.pop(key) + + return len(expired_keys) + + +# Глобальный менеджер +auto_delete_manager = AutoDeleteManager() + + +# ================= УДОБНЫЕ ФУНКЦИИ ================= + +async def auto_delete_message( + bot: Bot, + chat_id: int, + message_id: int, + delay: int = 604800, + reason: Optional[str] = None +) -> DeleteTask: + """ + Автоматически удаляет сообщение через указанное время. + + Args: + bot: Экземпляр бота + chat_id: ID чата + message_id: ID сообщения + delay: Задержка в секундах (по умолчанию 7 дней) + reason: Причина удаления + + Returns: + DeleteTask: Созданная задача + + Example: + >> # Удалить через 1 минуту + >> await auto_delete_message(bot, chat_id, message_id, delay=60) + + >> # Удалить через 7 дней (по умолчанию) + >> await auto_delete_message(bot, chat_id, message_id) + """ + return await auto_delete_manager.schedule( + bot=bot, + chat_id=chat_id, + message_id=message_id, + delay=delay, + reason=reason + ) + + +async def schedule_delete( + message: Message, + delay: int, + reason: Optional[str] = None +) -> DeleteTask: + """ + Планирует удаление сообщения (упрощенная версия). + + Args: + message: Объект сообщения + delay: Задержка в секундах + reason: Причина удаления + + Returns: + DeleteTask: Созданная задача + + Example: + >> # Планируем удаление через 30 секунд + >> await schedule_delete(message, delay=30, reason="Временное") + """ + return await auto_delete_manager.schedule( + bot=message.bot, + chat_id=message.chat.id, + message_id=message.message_id, + delay=delay, + reason=reason + ) + + +def cancel_delete(message: Message) -> bool: + """ + Отменяет запланированное удаление сообщения. + + Args: + message: Объект сообщения + + Returns: + bool: True если удаление было отменено + + Example: + >> if cancel_delete(message): + ... await message.answer("Удаление отменено") + """ + return auto_delete_manager.cancel( + chat_id=message.chat.id, + message_id=message.message_id + ) + + +async def delete_after( + message: Message, + text: str, + delay: int = 10, + **kwargs +) -> Message: + """ + Отправляет сообщение и автоматически удаляет его через указанное время. + + Args: + message: Исходное сообщение + text: Текст нового сообщения + delay: Задержка до удаления в секундах + **kwargs: Дополнительные параметры для message.answer() + + Returns: + Message: Отправленное сообщение + + Example: + >> # Отправить и удалить через 10 секунд + >> await delete_after(message, "Это временное сообщение") + + >> # Отправить и удалить через 5 секунд + >> await delete_after( + ... message, + ... "⚠️ Ошибка!", + ... delay=5, + ... parse_mode="HTML" + ... ) + """ + sent_message = await message.answer(text, **kwargs) + + await auto_delete_manager.schedule( + bot=message.bot, + chat_id=sent_message.chat.id, + message_id=sent_message.message_id, + delay=delay, + reason="delete_after" + ) + + return sent_message + + +async def delete_both_after( + original: Message, + reply_text: str, + delay: int = 10, + **kwargs +) -> Message: + """ + Отправляет ответ и удаляет оба сообщения через указанное время. + + Args: + original: Исходное сообщение + reply_text: Текст ответа + delay: Задержка до удаления + **kwargs: Дополнительные параметры + + Returns: + Message: Отправленное сообщение + + Example: + >> # Удалить и команду, и ответ через 5 секунд + >> await delete_both_after( + ... message, + ... "✅ Команда выполнена", + ... delay=5 + ... ) + """ + # Отправляем ответ + sent = await delete_after(original, reply_text, delay, **kwargs) + + # Планируем удаление оригинала + await auto_delete_manager.schedule( + bot=original.bot, + chat_id=original.chat.id, + message_id=original.message_id, + delay=delay, + reason="delete_both" + ) + + return sent + + +async def delete_messages_after( + bot: Bot, + chat_id: int, + message_ids: list[int], + delay: int +) -> int: + """ + Планирует удаление нескольких сообщений. + + Args: + bot: Экземпляр бота + chat_id: ID чата + message_ids: Список ID сообщений + delay: Задержка до удаления + + Returns: + int: Количество запланированных удалений + + Example: + >> # Удалить все сообщения через 1 час + >> count = await delete_messages_after( + ... bot, + ... chat_id, + ... [123, 124, 125, 126], + ... delay=3600 + ... ) + """ + count = 0 + + for message_id in message_ids: + await auto_delete_manager.schedule( + bot=bot, + chat_id=chat_id, + message_id=message_id, + delay=delay, + reason="mass_delete", + log=False + ) + count += 1 + + logger.info( + f"Запланировано удаление {count} сообщений через {format_duration(delay)}", + log_type='AUTO_DELETE' + ) + + return count diff --git a/bot/utils/decorators.py b/bot/utils/decorators.py new file mode 100644 index 0000000..21b424f --- /dev/null +++ b/bot/utils/decorators.py @@ -0,0 +1,812 @@ +""" +Декораторы для обработчиков бота +""" +import asyncio +from typing import Callable, Optional, Union +from functools import wraps +from datetime import datetime +from collections import defaultdict + +from aiogram.types import Message, CallbackQuery +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError +from aiogram.enums import ChatType, ChatMemberStatus + +from middleware.loggers import logger +from .format_time import format_duration + +__all__ = ( + 'admin_only', + 'owner_only', + 'private_only', + 'group_only', + 'rate_limit', + 'cooldown', + 'log_action', + 'catch_errors', + 'typing_action', + 'delete_command', + 'answer_on_error', + 'permission_required', + 'throttle', + 'admin_action' +) + + +# ================= ХРАНИЛИЩА ДЛЯ RATE LIMIT ================= + +class RateLimitStorage: + """Хранилище для rate limiting""" + + def __init__(self): + # {user_id: {action: datetime}} + self._storage: dict[int, dict[str, datetime]] = defaultdict(dict) + # {user_id: {action: count}} + self._counters: dict[int, dict[str, int]] = defaultdict(lambda: defaultdict(int)) + + def check( + self, + user_id: int, + action: str, + limit: int, + period: int + ) -> tuple[bool, Optional[int]]: + """ + Проверяет лимит. + + Returns: + tuple[bool, Optional[int]]: (можно ли выполнить, секунд до сброса) + """ + now = datetime.now() + + if action not in self._storage[user_id]: + # Первое использование + self._storage[user_id][action] = now + self._counters[user_id][action] = 1 + return True, None + + last_use = self._storage[user_id][action] + time_passed = (now - last_use).total_seconds() + + # Если прошел период - сбрасываем + if time_passed >= period: + self._storage[user_id][action] = now + self._counters[user_id][action] = 1 + return True, None + + # Проверяем счетчик + count = self._counters[user_id][action] + + if count >= limit: + # Превышен лимит + retry_after = int(period - time_passed) + return False, retry_after + + # Увеличиваем счетчик + self._counters[user_id][action] += 1 + return True, None + + def reset(self, user_id: int, action: Optional[str] = None): + """Сбрасывает лимит для пользователя""" + if action: + if user_id in self._storage: + self._storage[user_id].pop(action, None) + self._counters[user_id].pop(action, None) + else: + self._storage.pop(user_id, None) + self._counters.pop(user_id, None) + + def cleanup(self, max_age: int = 3600): + """Очищает старые записи""" + now = datetime.now() + expired_users = [] + + for user_id, actions in self._storage.items(): + expired_actions = [ + action for action, dt in actions.items() + if (now - dt).total_seconds() > max_age + ] + + for action in expired_actions: + actions.pop(action, None) + self._counters[user_id].pop(action, None) + + if not actions: + expired_users.append(user_id) + + for user_id in expired_users: + self._storage.pop(user_id, None) + self._counters.pop(user_id, None) + + +# Глобальное хранилище +_rate_limit_storage = RateLimitStorage() +_cooldown_storage = RateLimitStorage() + + +# ================= ПРОВЕРКА ПРАВ ================= + +async def _check_admin_rights( + message: Message, + user_id: Optional[int] = None +) -> bool: + """ + Проверяет, является ли пользователь администратором. + + Args: + message: Объект сообщения + user_id: ID пользователя (если None, проверяется отправитель) + + Returns: + bool: True если администратор + """ + # В личных сообщениях все пользователи "администраторы" + if message.chat.type == ChatType.PRIVATE: + return True + + check_user_id = user_id or message.from_user.id + + try: + member = await message.bot.get_chat_member( + chat_id=message.chat.id, + user_id=check_user_id + ) + + return member.status in { + ChatMemberStatus.CREATOR, + ChatMemberStatus.ADMINISTRATOR + } + + except (TelegramBadRequest, TelegramForbiddenError): + return False + + +async def _check_owner_rights(message: Message) -> bool: + """Проверяет, является ли пользователь владельцем чата""" + if message.chat.type == ChatType.PRIVATE: + return True + + try: + member = await message.bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + return member.status == ChatMemberStatus.CREATOR + + except (TelegramBadRequest, TelegramForbiddenError): + return False + + +async def _check_bot_admin_rights(message: Message) -> bool: + """Проверяет, является ли бот администратором""" + if message.chat.type == ChatType.PRIVATE: + return True + + try: + bot_member = await message.bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.bot.id + ) + + return bot_member.status in { + ChatMemberStatus.ADMINISTRATOR + } + + except (TelegramBadRequest, TelegramForbiddenError): + return False + + +# ================= ДЕКОРАТОРЫ ДЛЯ ПРАВ ================= + +def admin_only( + reply_text: str = "❌ Эта команда доступна только администраторам", + check_bot: bool = False +): + """ + Декоратор: выполнение только для администраторов. + + Args: + reply_text: Текст ответа если не админ + check_bot: Также проверять права бота + + Example: + ```python + @router.message(Command("ban")) + @admin_only() + async def ban_handler(message: Message): + await message.answer("Бан пользователя...") + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + # Получаем message + message = update if isinstance(update, Message) else update.message + + if not message: + return None + + # Проверяем права пользователя + if not await _check_admin_rights(message): + if isinstance(update, CallbackQuery): + await update.answer(reply_text, show_alert=True) + else: + await message.answer(reply_text) + + logger.warning( + f"Попытка использования admin команды от @{message.from_user.id}", + log_type='SECURITY' + ) + return None + + # Проверяем права бота если нужно + if check_bot and not await _check_bot_admin_rights(message): + error_text = "❌ Бот не является администратором чата" + + if isinstance(update, CallbackQuery): + await update.answer(error_text, show_alert=True) + else: + await message.answer(error_text) + return None + + return await func(update, *args, **kwargs) + + return wrapper + + return decorator + + +def owner_only(reply_text: str = "❌ Эта команда доступна только владельцу чата"): + """ + Декоратор: выполнение только для владельца чата. + + Args: + reply_text: Текст ответа если не владелец + + Example: + ```python + @router.message(Command("destroy")) + @owner_only() + async def destroy_handler(message: Message): + await message.answer("Удаление чата...") + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return None + + if not await _check_owner_rights(message): + if isinstance(update, CallbackQuery): + await update.answer(reply_text, show_alert=True) + else: + await message.answer(reply_text) + + logger.warning( + f"Попытка использования owner команды от @{message.from_user.id}", + log_type='SECURITY' + ) + return None + + return await func(update, *args, **kwargs) + + return wrapper + + return decorator + + +def permission_required(*permissions: str): + """ + Декоратор: проверка конкретных прав администратора. + + Args: + permissions: Список прав (can_delete_messages, can_restrict_members, и т.д.) + + Example: + ```python + @router.message(Command("pin")) + @permission_required("can_pin_messages") + async def pin_handler(message: Message): + await message.reply_to_message.pin() + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return None + + # В личных сообщениях пропускаем проверку + if message.chat.type == ChatType.PRIVATE: + return await func(update, *args, **kwargs) + + try: + member = await message.bot.get_chat_member( + chat_id=message.chat.id, + user_id=message.from_user.id + ) + + # Владелец имеет все права + if member.status == ChatMemberStatus.CREATOR: + return await func(update, *args, **kwargs) + + # Проверяем права + if member.status == ChatMemberStatus.ADMINISTRATOR: + missing_permissions = [] + + for perm in permissions: + if not getattr(member, perm, False): + missing_permissions.append(perm) + + if missing_permissions: + error_text = ( + f"❌ Недостаточно прав\n" + f"Требуются: {', '.join(missing_permissions)}" + ) + + if isinstance(update, CallbackQuery): + await update.answer(error_text, show_alert=True) + else: + await message.answer(error_text) + return None + + return await func(update, *args, **kwargs) + + # Не администратор + error_text = "❌ Эта команда доступна только администраторам" + + if isinstance(update, CallbackQuery): + await update.answer(error_text, show_alert=True) + else: + await message.answer(error_text) + + except (TelegramBadRequest, TelegramForbiddenError): + pass + + return wrapper + + return decorator + + +# ================= ДЕКОРАТОРЫ ДЛЯ ТИПОВ ЧАТОВ ================= + +def private_only(reply_text: str = "❌ Эта команда работает только в личных сообщениях"): + """ + Декоратор: выполнение только в личных сообщениях. + + Example: + ```python + @router.message(Command("start")) + @private_only() + async def start_handler(message: Message): + await message.answer("Приветствие...") + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return None + + if message.chat.type != ChatType.PRIVATE: + if isinstance(update, CallbackQuery): + await update.answer(reply_text, show_alert=True) + else: + await message.answer(reply_text) + return None + + return await func(update, *args, **kwargs) + + return wrapper + + return decorator + + +def group_only(reply_text: str = "❌ Эта команда работает только в группах"): + """ + Декоратор: выполнение только в группах. + + Example: + ```python + @router.message(Command("ban")) + @group_only() + async def ban_handler(message: Message): + await message.answer("Бан пользователя...") + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return None + + if message.chat.type not in {ChatType.GROUP, ChatType.SUPERGROUP}: + if isinstance(update, CallbackQuery): + await update.answer(reply_text, show_alert=True) + else: + await message.answer(reply_text) + return None + + return await func(update, *args, **kwargs) + + return wrapper + + return decorator + + +# ================= RATE LIMITING ================= + +def rate_limit(limit: int = 1, period: int = 60, action: Optional[str] = None): + """ + Декоратор: ограничение частоты вызовов. + + Args: + limit: Количество вызовов + period: Период в секундах + action: Название действия (по умолчанию имя функции) + + Example: + ```python + @router.message(Command("search")) + @rate_limit(limit=3, period=60) # 3 раза в минуту + async def search_handler(message: Message): + await message.answer("Поиск...") + ``` + """ + + def decorator(func: Callable) -> Callable: + action_name = action or func.__name__ + + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return None + + user_id = message.from_user.id + + # Проверяем лимит + allowed, retry_after = _rate_limit_storage.check( + user_id, action_name, limit, period + ) + + if not allowed: + retry_time = format_duration(retry_after) + error_text = f"⏳ Слишком часто! Повторите через {retry_time}" + + if isinstance(update, CallbackQuery): + await update.answer(error_text, show_alert=True) + else: + await message.answer(error_text) + + logger.debug( + f"Rate limit для пользователя {user_id}: {action_name}", + log_type='RATE_LIMIT' + ) + return None + + return await func(update, *args, **kwargs) + + return wrapper + + return decorator + + +def cooldown(seconds: int, action: Optional[str] = None): + """ + Декоратор: кулдаун между вызовами (1 раз в N секунд). + + Args: + seconds: Кулдаун в секундах + action: Название действия + + Example: + ```python + @router.message(Command("daily")) + @cooldown(seconds=86400) # Раз в день + async def daily_handler(message: Message): + await message.answer("Ежедневная награда!") + ``` + """ + return rate_limit(limit=1, period=seconds, action=action) + + +def throttle(rate: float = 1.0): + """ + Декоратор: throttling (antiflood). + + Args: + rate: Минимальный интервал в секундах между вызовами + + Example: + ```python + @router.message() + @throttle(rate=0.5) # Не чаще 2 раз в секунду + async def echo_handler(message: Message): + await message.answer(message.text) + ``` + """ + return cooldown(seconds=int(rate), action='throttle') + + +# ================= ЛОГИРОВАНИЕ ================= + +def log_action( + action_name: Optional[str] = None, + log_args: bool = False +): + """ + Декоратор: логирование действий. + + Args: + action_name: Название действия (по умолчанию имя функции) + log_args: Логировать аргументы + + Example: + ```python + @router.message(Command("ban")) + @log_action("BAN_USER", log_args=True) + async def ban_handler(message: Message): + await message.answer("Бан...") + ``` + """ + + def decorator(func: Callable) -> Callable: + name = action_name or func.__name__ + + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return await func(update, *args, **kwargs) + + user_id = message.from_user.id + username = message.from_user.username or f"id{user_id}" + + # Логируем начало + log_msg = f"Действие '{name}' от @{username}" + + if log_args and message.text: + log_msg += f" | Аргументы: {message.text}" + + logger.info(log_msg, log_type='ACTION') + + try: + result = await func(update, *args, **kwargs) + logger.info(f"Действие '{name}' выполнено успешно", log_type='ACTION') + return result + + except Exception as e: + logger.error(f"Ошибка в действии '{name}': {e}", log_type='ACTION') + raise + + return wrapper + + return decorator + + +# ================= ОБРАБОТКА ОШИБОК ================= + +def catch_errors( + notify_user: bool = True, + error_message: str = "❌ Произошла ошибка при выполнении команды" +): + """ + Декоратор: перехват ошибок. + + Args: + notify_user: Уведомлять пользователя об ошибке + error_message: Текст уведомления + + Example: + ```python + @router.message(Command("risky")) + @catch_errors(notify_user=True) + async def risky_handler(message: Message): + # Код который может вызвать ошибку + ... + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + try: + return await func(update, *args, **kwargs) + + except Exception as e: + logger.error( + f"Ошибка в {func.__name__}: {e}", + log_type='ERROR' + ) + + if notify_user: + message = update if isinstance(update, Message) else update.message + + if message: + try: + if isinstance(update, CallbackQuery): + await update.answer(error_message, show_alert=True) + else: + await message.answer(error_message) + except: + pass + + return wrapper + + return decorator + + +def answer_on_error(error_message: str = "❌ Ошибка"): + """ + Декоратор: ответ пользователю при ошибке. + + Alias для catch_errors с уведомлением. + """ + return catch_errors(notify_user=True, error_message=error_message) + + +# ================= ДЕЙСТВИЯ ================= + +def typing_action(): + """ + Декоратор: показывает "печатает..." во время выполнения. + + Example: + ```python + @router.message(Command("search")) + @typing_action() + async def search_handler(message: Message): + # Долгий поиск... + await asyncio.sleep(3) + await message.answer("Результаты поиска") + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(update: Union[Message, CallbackQuery], *args, **kwargs): + message = update if isinstance(update, Message) else update.message + + if not message: + return await func(update, *args, **kwargs) + + # Отправляем действие "печатает" + async def send_typing(): + try: + while True: + await message.bot.send_chat_action( + chat_id=message.chat.id, + action="typing" + ) + await asyncio.sleep(4) # Обновляем каждые 4 секунды + except asyncio.CancelledError: + pass + + # Создаем задачу + typing_task = asyncio.create_task(send_typing()) + + try: + result = await func(update, *args, **kwargs) + return result + finally: + typing_task.cancel() + try: + await typing_task + except asyncio.CancelledError: + pass + + return wrapper + + return decorator + + +def delete_command(delay: Optional[int] = None): + """ + Декоратор: удаляет команду после выполнения. + + Args: + delay: Задержка перед удалением (секунды) + + Example: + ```python + @router.message(Command("clean")) + @delete_command(delay=0) + async def clean_handler(message: Message): + await message.answer("Очистка...") + ``` + """ + + def decorator(func: Callable) -> Callable: + @wraps(func) + async def wrapper(message: Message, *args, **kwargs): + if not isinstance(message, Message): + return await func(message, *args, **kwargs) + + # Выполняем функцию + result = await func(message, *args, **kwargs) + + # Удаляем команду + try: + if delay: + await asyncio.sleep(delay) + + await message.delete() + except (TelegramBadRequest, TelegramForbiddenError): + pass + + return result + + return wrapper + + return decorator + + +# ================= КОМБИНИРОВАННЫЕ ДЕКОРАТОРЫ ================= + +def admin_action( + log: bool = True, + check_bot: bool = True, + delete_cmd: bool = False +): + """ + Комбинированный декоратор для admin команд. + + Args: + log: Логировать действие + check_bot: Проверять права бота + delete_cmd: Удалять команду + + Example: + ```python + @router.message(Command("ban")) + @admin_action(log=True, check_bot=True) + async def ban_handler(message: Message): + await message.answer("Бан...") + ``` + """ + + def decorator(func: Callable) -> Callable: + # Применяем декораторы + decorated = func + + if log: + decorated = log_action(f"ADMIN_{func.__name__.upper()}")(decorated) + + decorated = admin_only(check_bot=check_bot)(decorated) + + if delete_cmd: + decorated = delete_command()(decorated) + + return decorated + + return decorator + + +# ================= ОЧИСТКА ХРАНИЛИЩ ================= + +def cleanup_storage(max_age: int = 3600): + """ + Очищает хранилища rate limit от старых записей. + + Args: + max_age: Максимальный возраст записи в секундах + """ + _rate_limit_storage.cleanup(max_age) + _cooldown_storage.cleanup(max_age) diff --git a/bot/utils/format_time.py b/bot/utils/format_time.py new file mode 100644 index 0000000..91e4f0d --- /dev/null +++ b/bot/utils/format_time.py @@ -0,0 +1,523 @@ +""" +Утилиты для форматирования времени и дат +""" +from typing import Optional, Union +from datetime import datetime, timedelta +from enum import Enum + +__all__ = ( + 'format_duration', + 'format_retry_time', + 'format_timestamp', + 'format_relative_time', + 'parse_duration', + 'TimeFormat', + 'get_plural_form', + 'seconds_to_human', + 'time_until', + 'time_since', + 'format_date_range', + 'is_today', + 'is_yesterday', + 'is_tomorrow', + 'smart_date' +) + + +class TimeFormat(str, Enum): + """Форматы времени""" + FULL = 'full' # 1 час 30 минут 45 секунд + SHORT = 'short' # 1ч 30м 45с + COMPACT = 'compact' # 1:30:45 + MINIMAL = 'minimal' # 1ч 30м (без секунд если есть часы/минуты) + + +def get_plural_form(number: int, forms: tuple[str, str, str]) -> str: + """ + Возвращает правильную форму множественного числа для русского языка. + + Args: + number: Число + forms: Кортеж форм (1 секунда, 2 секунды, 5 секунд) + + Returns: + str: Правильная форма + + Example: + >> get_plural_form(1, ('секунда', 'секунды', 'секунд')) + 'секунда' + >> get_plural_form(2, ('секунда', 'секунды', 'секунд')) + 'секунды' + >> get_plural_form(5, ('секунда', 'секунды', 'секунд')) + 'секунд' + """ + n = abs(number) + n %= 100 + + if 5 <= n <= 20: + return forms[2] + + n %= 10 + + if n == 1: + return forms[0] + elif 2 <= n <= 4: + return forms[1] + else: + return forms[2] + + +def format_duration( + seconds: int, + format_type: TimeFormat = TimeFormat.FULL, + include_seconds: bool = True, + max_units: Optional[int] = None +) -> str: + """ + Форматирует длительность в читаемый вид. + + Args: + seconds: Длительность в секундах + format_type: Тип форматирования + include_seconds: Включать секунды в вывод + max_units: Максимальное количество единиц времени (например, только часы и минуты) + + Returns: + str: Отформатированная строка + + Example: + >> format_duration(3665) + '1 час 1 минута 5 секунд' + + >> format_duration(3665, TimeFormat.SHORT) + '1ч 1м 5с' + + >> format_duration(3665, TimeFormat.COMPACT) + '1:01:05' + + >> format_duration(3665, max_units=2) + '1 час 1 минута' + """ + if seconds == 0: + if format_type == TimeFormat.FULL: + return "0 секунд" + elif format_type == TimeFormat.SHORT: + return "0с" + elif format_type == TimeFormat.COMPACT: + return "0:00" + else: + return "0с" + + # Разбиваем на единицы + weeks, remainder = divmod(seconds, 604800) # 7 * 24 * 60 * 60 + days, remainder = divmod(remainder, 86400) # 24 * 60 * 60 + hours, remainder = divmod(remainder, 3600) + minutes, secs = divmod(remainder, 60) + + # Компактный формат + if format_type == TimeFormat.COMPACT: + if weeks > 0: + return f"{weeks * 7 + days}д {hours:02d}:{minutes:02d}:{secs:02d}" + elif days > 0: + return f"{days}д {hours:02d}:{minutes:02d}:{secs:02d}" + elif hours > 0: + return f"{hours}:{minutes:02d}:{secs:02d}" + elif minutes > 0: + return f"{minutes}:{secs:02d}" + else: + return f"0:{secs:02d}" + + # Собираем части + parts = [] + units_count = 0 + + # Недели + if weeks > 0: + if format_type == TimeFormat.SHORT: + parts.append(f"{weeks}нед") + else: + week_form = get_plural_form(weeks, ('неделя', 'недели', 'недель')) + parts.append(f"{weeks} {week_form}") + units_count += 1 + if max_units and units_count >= max_units: + return ' '.join(parts) + + # Дни + if days > 0: + if format_type == TimeFormat.SHORT: + parts.append(f"{days}д") + else: + day_form = get_plural_form(days, ('день', 'дня', 'дней')) + parts.append(f"{days} {day_form}") + units_count += 1 + if max_units and units_count >= max_units: + return ' '.join(parts) + + # Часы + if hours > 0: + if format_type == TimeFormat.SHORT: + parts.append(f"{hours}ч") + else: + hour_form = get_plural_form(hours, ('час', 'часа', 'часов')) + parts.append(f"{hours} {hour_form}") + units_count += 1 + if max_units and units_count >= max_units: + return ' '.join(parts) + + # Минуты + if minutes > 0: + if format_type == TimeFormat.SHORT: + parts.append(f"{minutes}м") + else: + minute_form = get_plural_form(minutes, ('минута', 'минуты', 'минут')) + parts.append(f"{minutes} {minute_form}") + units_count += 1 + if max_units and units_count >= max_units: + return ' '.join(parts) + + # Секунды + if secs > 0 and include_seconds: + # Минимальный формат: не показываем секунды если есть часы или дни + if format_type == TimeFormat.MINIMAL and (hours > 0 or days > 0 or weeks > 0): + pass + else: + if format_type == TimeFormat.SHORT: + parts.append(f"{secs}с") + else: + second_form = get_plural_form(secs, ('секунда', 'секунды', 'секунд')) + parts.append(f"{secs} {second_form}") + + return ' '.join(parts) if parts else "0 секунд" + + +def format_retry_time(retry_after: int, format_type: TimeFormat = TimeFormat.FULL) -> str: + """ + Форматирует время повторной попытки. + + Args: + retry_after: Время в секундах до следующей попытки + format_type: Тип форматирования + + Returns: + str: Отформатированная строка + + Example: + >> format_retry_time(3665) + '1 час 1 минута 5 секунд' + + >> format_retry_time(3665, TimeFormat.SHORT) + '1ч 1м 5с' + """ + return format_duration(retry_after, format_type=format_type) + + +def format_timestamp( + timestamp: Union[int, float, datetime], + format_string: str = "%d.%m.%Y %H:%M:%S", + timezone_offset: Optional[int] = None +) -> str: + """ + Форматирует timestamp в читаемую дату. + + Args: + timestamp: Unix timestamp или datetime объект + format_string: Формат вывода + timezone_offset: Смещение часового пояса в часах + + Returns: + str: Отформатированная дата + + Example: + >> format_timestamp(1640000000) + '20.12.2021 13:33:20' + + >> format_timestamp(datetime.now(), "%d %B %Y") + '17 февраля 2026' + """ + if isinstance(timestamp, (int, float)): + dt = datetime.fromtimestamp(timestamp) + else: + dt = timestamp + + # Применяем смещение часового пояса + if timezone_offset is not None: + dt = dt + timedelta(hours=timezone_offset) + + return dt.strftime(format_string) + + +def format_relative_time( + timestamp: Union[int, float, datetime], + now: Optional[datetime] = None, + detailed: bool = False +) -> str: + """ + Форматирует время относительно текущего момента. + + Args: + timestamp: Unix timestamp или datetime объект + now: Текущее время (по умолчанию datetime.now()) + detailed: Детальный формат (например "2 часа 30 минут назад" вместо "2 часа назад") + + Returns: + str: Относительное время + + Example: + >> format_relative_time(time.time() - 3600) + '1 час назад' + + >> format_relative_time(time.time() + 7200) + 'через 2 часа' + + >> format_relative_time(time.time() - 90, detailed=True) + '1 минута 30 секунд назад' + """ + if now is None: + now = datetime.now() + + if isinstance(timestamp, (int, float)): + dt = datetime.fromtimestamp(timestamp) + else: + dt = timestamp + + # Вычисляем разницу + delta = now - dt + is_past = delta.total_seconds() > 0 + + seconds = abs(int(delta.total_seconds())) + + # Если меньше минуты + if seconds < 60: + if is_past: + return "только что" + else: + return "сейчас" + + # Форматируем длительность + if detailed: + duration = format_duration(seconds, TimeFormat.FULL, max_units=2) + else: + duration = format_duration(seconds, TimeFormat.FULL, max_units=1) + + if is_past: + return f"{duration} назад" + else: + return f"через {duration}" + + +def parse_duration(duration_str: str) -> Optional[int]: + """ + Парсит строку длительности в секунды. + + Args: + duration_str: Строка длительности (например "1ч 30м", "2h 15m", "90s") + + Returns: + Optional[int]: Длительность в секундах или None если не удалось распарсить + + Example: + >> parse_duration("1ч 30м") + 5400 + + >> parse_duration("2h 15m 30s") + 8130 + + >> parse_duration("90s") + 90 + """ + import re + + # Паттерны для разных единиц + patterns = { + 'weeks': r'(\d+)\s*(?:нед|w|week|weeks)', + 'days': r'(\d+)\s*(?:д|d|day|days)', + 'hours': r'(\d+)\s*(?:ч|h|hour|hours)', + 'minutes': r'(\d+)\s*(?:м|m|min|minutes)', + 'seconds': r'(\d+)\s*(?:с|s|sec|seconds)' + } + + total_seconds = 0 + + # Ищем каждую единицу + for unit, pattern in patterns.items(): + match = re.search(pattern, duration_str, re.IGNORECASE) + if match: + value = int(match.group(1)) + + if unit == 'weeks': + total_seconds += value * 604800 + elif unit == 'days': + total_seconds += value * 86400 + elif unit == 'hours': + total_seconds += value * 3600 + elif unit == 'minutes': + total_seconds += value * 60 + elif unit == 'seconds': + total_seconds += value + + return total_seconds if total_seconds > 0 else None + + +# ================= ДОПОЛНИТЕЛЬНЫЕ УТИЛИТЫ ================= + +def seconds_to_human(seconds: int) -> str: + """ + Преобразует секунды в человекопонятный формат (самая большая единица). + + Args: + seconds: Количество секунд + + Returns: + str: Человекопонятный формат + + Example: + >> seconds_to_human(3600) + '1 час' + + >> seconds_to_human(90) + '1.5 минуты' + """ + if seconds >= 604800: # Неделя + weeks = seconds / 604800 + week_form = get_plural_form(int(weeks), ('неделя', 'недели', 'недель')) + return f"{weeks:.1f} {week_form}".replace('.0', '') + elif seconds >= 86400: # День + days = seconds / 86400 + day_form = get_plural_form(int(days), ('день', 'дня', 'дней')) + return f"{days:.1f} {day_form}".replace('.0', '') + elif seconds >= 3600: # Час + hours = seconds / 3600 + hour_form = get_plural_form(int(hours), ('час', 'часа', 'часов')) + return f"{hours:.1f} {hour_form}".replace('.0', '') + elif seconds >= 60: # Минута + minutes = seconds / 60 + minute_form = get_plural_form(int(minutes), ('минута', 'минуты', 'минут')) + return f"{minutes:.1f} {minute_form}".replace('.0', '') + else: # Секунда + second_form = get_plural_form(seconds, ('секунда', 'секунды', 'секунд')) + return f"{seconds} {second_form}" + + +def time_until(target_time: datetime, format_type: TimeFormat = TimeFormat.FULL) -> str: + """ + Возвращает время до указанного момента. + + Args: + target_time: Целевое время + format_type: Тип форматирования + + Returns: + str: Отформатированное время + + Example: + >> target = datetime.now() + timedelta(hours=2, minutes=30) + >> time_until(target) + '2 часа 30 минут' + """ + now = datetime.now() + delta = target_time - now + + if delta.total_seconds() <= 0: + return "уже прошло" + + seconds = int(delta.total_seconds()) + return format_duration(seconds, format_type=format_type) + + +def time_since(start_time: datetime, format_type: TimeFormat = TimeFormat.FULL) -> str: + """ + Возвращает время с указанного момента. + + Args: + start_time: Начальное время + format_type: Тип форматирования + + Returns: + str: Отформатированное время + + Example: + >> start = datetime.now() - timedelta(hours=1, minutes=15) + >> time_since(start) + '1 час 15 минут' + """ + now = datetime.now() + delta = now - start_time + + if delta.total_seconds() <= 0: + return "еще не началось" + + seconds = int(delta.total_seconds()) + return format_duration(seconds, format_type=format_type) + + +def format_date_range(start: datetime, end: datetime) -> str: + """ + Форматирует диапазон дат. + + Args: + start: Начальная дата + end: Конечная дата + + Returns: + str: Отформатированный диапазон + + Example: + >> start = datetime(2026, 2, 17, 10, 0) + >> end = datetime(2026, 2, 17, 18, 0) + >> format_date_range(start, end) + '17.02.2026 с 10:00 до 18:00' + """ + if start.date() == end.date(): + # Один день + return f"{start.strftime('%d.%m.%Y')} с {start.strftime('%H:%M')} до {end.strftime('%H:%M')}" + else: + # Разные дни + return f"с {start.strftime('%d.%m.%Y %H:%M')} до {end.strftime('%d.%m.%Y %H:%M')}" + + +def is_today(dt: datetime) -> bool: + """Проверяет, является ли дата сегодняшней""" + return dt.date() == datetime.now().date() + + +def is_yesterday(dt: datetime) -> bool: + """Проверяет, является ли дата вчерашней""" + yesterday = datetime.now().date() - timedelta(days=1) + return dt.date() == yesterday + + +def is_tomorrow(dt: datetime) -> bool: + """Проверяет, является ли дата завтрашней""" + tomorrow = datetime.now().date() + timedelta(days=1) + return dt.date() == tomorrow + + +def smart_date(dt: datetime) -> str: + """ + Умное форматирование даты (сегодня, вчера, завтра, или дата). + + Args: + dt: Дата для форматирования + + Returns: + str: Отформатированная дата + + Example: + >> smart_date(datetime.now()) + 'сегодня в 14:30' + + >> smart_date(datetime.now() - timedelta(days=1)) + 'вчера в 20:15' + """ + if is_today(dt): + return f"сегодня в {dt.strftime('%H:%M')}" + elif is_yesterday(dt): + return f"вчера в {dt.strftime('%H:%M')}" + elif is_tomorrow(dt): + return f"завтра в {dt.strftime('%H:%M')}" + else: + # Если в этом году, не показываем год + if dt.year == datetime.now().year: + return dt.strftime('%d.%m в %H:%M') + else: + return dt.strftime('%d.%m.%Y в %H:%M') diff --git a/bot/utils/hidden_username.py b/bot/utils/hidden_username.py new file mode 100644 index 0000000..8d2472c --- /dev/null +++ b/bot/utils/hidden_username.py @@ -0,0 +1,504 @@ +""" +Утилиты для упоминаний пользователей (mentions) +""" +from typing import Optional, List, Set +from datetime import datetime, timedelta + +from aiogram import Bot +from aiogram.types import Message, ChatMemberAdministrator, ChatMemberOwner, User +from aiogram.utils.markdown import hide_link, hlink +from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError + +__all__ = ( + 'mention_admins', + 'mention_user', + 'mention_users', + 'get_admins_list', + 'AdminCache', + 'admin_cache', + 'mention_moderators', + 'mention_owner', + 'hidden_admins_message' +) + + +class AdminCache: + """ + Кэш для списков администраторов чатов. + + Уменьшает количество запросов к API Telegram. + """ + + def __init__(self, ttl: int = 300): + """ + Args: + ttl: Время жизни кэша в секундах (по умолчанию 5 минут) + """ + self.ttl = ttl + # {chat_id: (admins_list, timestamp)} + self._cache: dict[int, tuple[List[User], datetime]] = {} + # Статистика + self.hits: int = 0 + self.misses: int = 0 + + def get(self, chat_id: int) -> Optional[List[User]]: + """ + Получает список админов из кэша. + + Args: + chat_id: ID чата + + Returns: + List[User] или None если кэш устарел + """ + if chat_id in self._cache: + admins, timestamp = self._cache[chat_id] + + # Проверяем актуальность + if datetime.now() - timestamp < timedelta(seconds=self.ttl): + self.hits += 1 + return admins + else: + # Удаляем устаревшую запись + del self._cache[chat_id] + + self.misses += 1 + return None + + def set(self, chat_id: int, admins: List[User]) -> None: + """ + Сохраняет список админов в кэш. + + Args: + chat_id: ID чата + admins: Список администраторов + """ + self._cache[chat_id] = (admins, datetime.now()) + + def invalidate(self, chat_id: Optional[int] = None) -> None: + """ + Инвалидирует кэш. + + Args: + chat_id: ID чата (если None, очищает весь кэш) + """ + if chat_id is None: + self._cache.clear() + elif chat_id in self._cache: + del self._cache[chat_id] + + def cleanup(self) -> int: + """ + Удаляет устаревшие записи. + + Returns: + int: Количество удаленных записей + """ + now = datetime.now() + expired = [ + chat_id for chat_id, (_, timestamp) in self._cache.items() + if now - timestamp >= timedelta(seconds=self.ttl) + ] + + for chat_id in expired: + del self._cache[chat_id] + + return len(expired) + + def get_stats(self) -> dict: + """Возвращает статистику кэша""" + total = self.hits + self.misses + hit_rate = (self.hits / total * 100) if total > 0 else 0 + + return { + 'hits': self.hits, + 'misses': self.misses, + 'hit_rate': f"{hit_rate:.1f}%", + 'cached_chats': len(self._cache) + } + + +# Глобальный кэш +admin_cache = AdminCache(ttl=300) + + +async def get_admins_list( + bot: Bot, + chat_id: int, + exclude_bots: bool = True, + exclude_users: Optional[Set[int]] = None, + include_owner_only: bool = False, + use_cache: bool = True +) -> List[User]: + """ + Получает список администраторов чата. + + Args: + bot: Экземпляр бота + chat_id: ID чата + exclude_bots: Исключить ботов + exclude_users: Множество ID пользователей для исключения + include_owner_only: Только владелец чата + use_cache: Использовать кэш + + Returns: + List[User]: Список администраторов + + Example: + >> admins = await get_admins_list(bot, chat_id) + >> print(f"Администраторов: {len(admins)}") + """ + # Проверяем кэш + if use_cache: + cached_admins = admin_cache.get(chat_id) + if cached_admins is not None: + admins = cached_admins.copy() + else: + # Загружаем из API + try: + chat_admins = await bot.get_chat_administrators(chat_id) + admins = [admin.user for admin in chat_admins] + # Сохраняем в кэш + admin_cache.set(chat_id, admins) + except (TelegramBadRequest, TelegramForbiddenError): + return [] + else: + # Без кэша + try: + chat_admins = await bot.get_chat_administrators(chat_id) + admins = [admin.user for admin in chat_admins] + except (TelegramBadRequest, TelegramForbiddenError): + return [] + + # Фильтрация + filtered_admins = [] + + for admin_user in admins: + # Исключаем ботов + if exclude_bots and admin_user.is_bot: + continue + + # Исключаем конкретных пользователей + if exclude_users and admin_user.id in exclude_users: + continue + + filtered_admins.append(admin_user) + + # Только владелец + if include_owner_only and filtered_admins: + # Получаем информацию о владельце + try: + chat_admins = await bot.get_chat_administrators(chat_id) + owner = next( + (admin.user for admin in chat_admins if isinstance(admin, ChatMemberOwner)), + None + ) + if owner: + return [owner] + except: + pass + + return filtered_admins + + +async def mention_admins( + bot: Bot, + chat_id: int, + text: str = "", + format_type: str = "hidden", + exclude_bots: bool = True, + exclude_users: Optional[Set[int]] = None, + separator: str = " ", + use_cache: bool = True +) -> str: + """ + Формирует текст с упоминанием всех администраторов. + + Args: + bot: Экземпляр бота + chat_id: ID чата + text: Основной текст сообщения + format_type: Тип форматирования: + - 'hidden': Скрытые ссылки (невидимые) + - 'mention': HTML mentions (видимые имена) + - 'username': @username (только для пользователей с username) + - 'mixed': Mentions для пользователей с именами, hidden для остальных + exclude_bots: Исключить ботов + exclude_users: Множество ID пользователей для исключения + separator: Разделитель между mentions (для видимых форматов) + use_cache: Использовать кэш + + Returns: + str: Отформатированный текст с упоминаниями + + Example: + >> # Скрытые упоминания + >> text = await mention_admins(bot, chat_id, "Внимание, админы!") + >> await message.answer(text, parse_mode="HTML") + + >> # Видимые упоминания + >> text = await mention_admins(bot, chat_id, "Админы:", format_type="mention") + >> await message.answer(text, parse_mode="HTML") + """ + # Получаем список админов + admins = await get_admins_list( + bot=bot, + chat_id=chat_id, + exclude_bots=exclude_bots, + exclude_users=exclude_users, + use_cache=use_cache + ) + + if not admins: + return text + + # Формируем упоминания в зависимости от типа + mentions = [] + + if format_type == "hidden": + # Скрытые ссылки (невидимые) + for admin in admins: + mentions.append(hide_link(f"tg://user?id={admin.id}")) + + # Объединяем все ссылки и добавляем текст + return "".join(mentions) + text + + elif format_type == "mention": + # HTML mentions (видимые имена) + for admin in admins: + name = admin.full_name or admin.first_name or f"User {admin.id}" + mentions.append(hlink(name, f"tg://user?id={admin.id}")) + + mentions_text = separator.join(mentions) + return f"{text}\n\n{mentions_text}" if text else mentions_text + + elif format_type == "username": + # Только @username + for admin in admins: + if admin.username: + mentions.append(f"@{admin.username}") + + if not mentions: + # Fallback на hidden если нет username + return await mention_admins( + bot, chat_id, text, format_type="hidden", + exclude_bots=exclude_bots, exclude_users=exclude_users + ) + + mentions_text = separator.join(mentions) + return f"{text}\n\n{mentions_text}" if text else mentions_text + + elif format_type == "mixed": + # Mentions для пользователей с именами, hidden для остальных + hidden_links = [] + visible_mentions = [] + + for admin in admins: + if admin.username: + # Видимый mention + name = admin.full_name or admin.first_name or f"@{admin.username}" + visible_mentions.append(hlink(name, f"tg://user?id={admin.id}")) + else: + # Скрытая ссылка + hidden_links.append(hide_link(f"tg://user?id={admin.id}")) + + hidden_part = "".join(hidden_links) + visible_part = separator.join(visible_mentions) + + if text: + if visible_part: + return f"{hidden_part}{text}\n\n{visible_part}" + else: + return f"{hidden_part}{text}" + else: + return f"{hidden_part}{visible_part}" + + # По умолчанию - hidden + return text + + +async def mention_user( + user: User, + format_type: str = "mention", + show_username: bool = False +) -> str: + """ + Создает упоминание одного пользователя. + + Args: + user: Объект пользователя + format_type: Тип форматирования ('mention', 'hidden', 'username') + show_username: Показывать username вместо имени (для mention) + + Returns: + str: Отформатированное упоминание + + Example: + >> mention = await mention_user(message.from_user) + >> await message.answer(f"Привет, {mention}!", parse_mode="HTML") + """ + if format_type == "hidden": + return hide_link(f"tg://user?id={user.id}") + + elif format_type == "username": + if user.username: + return f"@{user.username}" + # Fallback на mention + return await mention_user(user, format_type="mention") + + else: # mention + if show_username and user.username: + display_name = f"@{user.username}" + else: + display_name = user.full_name or user.first_name or f"User {user.id}" + + return hlink(display_name, f"tg://user?id={user.id}") + + +async def mention_users( + users: List[User], + format_type: str = "mention", + separator: str = ", ", + max_count: Optional[int] = None +) -> str: + """ + Создает упоминания списка пользователей. + + Args: + users: Список пользователей + format_type: Тип форматирования + separator: Разделитель между упоминаниями + max_count: Максимальное количество упоминаний (остальные как "и еще N") + + Returns: + str: Отформатированные упоминания + + Example: + >> users = [msg.from_user, ...] + >> mentions = await mention_users(users, max_count=5) + >> await message.answer(f"Участники: {mentions}", parse_mode="HTML") + """ + if not users: + return "" + + # Ограничиваем количество + display_users = users[:max_count] if max_count else users + remaining = len(users) - len(display_users) if max_count else 0 + + # Создаем упоминания + mentions = [] + for user in display_users: + mention = await mention_user(user, format_type=format_type) + mentions.append(mention) + + result = separator.join(mentions) + + # Добавляем "и еще N" + if remaining > 0: + result += f" и еще {remaining}" + + return result + + +# ================= СПЕЦИАЛИЗИРОВАННЫЕ ФУНКЦИИ ================= + +async def mention_moderators( + bot: Bot, + chat_id: int, + text: str = "", + format_type: str = "hidden" +) -> str: + """ + Упоминает только модераторов (администраторов с правами на удаление/бан). + + Args: + bot: Экземпляр бота + chat_id: ID чата + text: Текст сообщения + format_type: Тип форматирования + + Returns: + str: Текст с упоминаниями модераторов + """ + try: + chat_admins = await bot.get_chat_administrators(chat_id) + + # Фильтруем только модераторов + moderators = [] + for admin in chat_admins: + if admin.user.is_bot: + continue + + # Владелец всегда модератор + if isinstance(admin, ChatMemberOwner): + moderators.append(admin.user) + continue + + # Проверяем права администратора + if isinstance(admin, ChatMemberAdministrator): + if admin.can_delete_messages and admin.can_restrict_members: + moderators.append(admin.user) + + # Формируем упоминания + if format_type == "hidden": + mentions = "".join(hide_link(f"tg://user?id={mod.id}") for mod in moderators) + return f"{mentions}{text}" + else: + mentions = [] + for mod in moderators: + name = mod.full_name or mod.first_name or f"Moderator {mod.id}" + mentions.append(hlink(name, f"tg://user?id={mod.id}")) + + mentions_text = ", ".join(mentions) + return f"{text}\n\n{mentions_text}" if text else mentions_text + + except (TelegramBadRequest, TelegramForbiddenError): + return text + + +async def mention_owner( + bot: Bot, + chat_id: int, + format_type: str = "mention" +) -> Optional[str]: + """ + Получает упоминание владельца чата. + + Args: + bot: Экземпляр бота + chat_id: ID чата + format_type: Тип форматирования + + Returns: + Optional[str]: Упоминание владельца или None + """ + try: + chat_admins = await bot.get_chat_administrators(chat_id) + owner = next( + (admin.user for admin in chat_admins if isinstance(admin, ChatMemberOwner)), + None + ) + + if owner: + return await mention_user(owner, format_type=format_type) + + except (TelegramBadRequest, TelegramForbiddenError): + pass + + return None + + +# Алиас для обратной совместимости +async def hidden_admins_message(message: Message, text: str = "") -> str: + """ + Алиас для mention_admins с format_type="hidden". + + DEPRECATED: Используйте mention_admins() вместо этого. + """ + from bot import bot + return await mention_admins( + bot=bot, + chat_id=message.chat.id, + text=text, + format_type="hidden" + ) diff --git a/bot/utils/state_utils.py b/bot/utils/state_utils.py new file mode 100644 index 0000000..3c87674 --- /dev/null +++ b/bot/utils/state_utils.py @@ -0,0 +1,650 @@ +""" +Утилиты для работы с FSM состояниями и обновлениями +""" +from typing import Optional, Any, Set, Union +from contextlib import suppress + +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import State +from aiogram.types import CallbackQuery, Message, ReplyKeyboardRemove +from aiogram.exceptions import TelegramBadRequest + +from middleware.loggers import logger + +__all__ = ( + 'clear_state', + 'answer_callback', + 'safe_answer_callback', + 'safe_delete_message', + 'safe_edit_message', + 'clear_state_keep_data', + 'get_state_data', + 'set_state_data', + 'update_state_data', + 'is_state_active', + 'inline_clear', + 'status_clear', + 'delete_messages', + 'set_state_with_data', + 'get_or_create_data', + 'increment_state_value', + 'append_to_state_list', + 'remove_from_state_list', + 'toggle_state_flag', + 'debug_state' +) + + +# ================= РАБОТА С FSM СОСТОЯНИЯМИ ================= + +async def clear_state( + state: FSMContext, + log: bool = True +) -> None: + """ + Очищает FSM состояние. + + Args: + state: Контекст FSM + log: Логировать очистку + + Example: + >> await clear_state(state) + """ + current_state = await state.get_state() + + if log and current_state: + logger.debug( + f"Очистка FSM состояния: {current_state}", + log_type='FSM' + ) + + await state.clear() + + +async def clear_state_keep_data( + state: FSMContext, + keep_keys: Optional[Set[str]] = None +) -> None: + """ + Очищает FSM состояние, но сохраняет определенные данные. + + Args: + state: Контекст FSM + keep_keys: Множество ключей для сохранения + + Example: + >> # Очищаем состояние, но сохраняем user_id и language + >> await clear_state_keep_data(state, keep_keys={'user_id', 'language'}) + """ + if keep_keys: + # Получаем текущие данные + current_data = await state.get_data() + + # Сохраняем только нужные ключи + saved_data = { + key: value for key, value in current_data.items() + if key in keep_keys + } + + # Очищаем состояние + await state.clear() + + # Восстанавливаем сохраненные данные + if saved_data: + await state.update_data(**saved_data) + + logger.debug( + f"FSM очищен, сохранены ключи: {', '.join(keep_keys)}", + log_type='FSM' + ) + else: + await state.clear() + + +async def get_state_data( + state: FSMContext, + key: Optional[str] = None, + default: Any = None +) -> Any: + """ + Получает данные из FSM состояния. + + Args: + state: Контекст FSM + key: Ключ для получения (если None, возвращает все данные) + default: Значение по умолчанию + + Returns: + Any: Данные из состояния + + Example: + >> # Получить все данные + >> data = await get_state_data(state) + + >> # Получить конкретный ключ + >> user_id = await get_state_data(state, 'user_id') + + >> # С значением по умолчанию + >> lang = await get_state_data(state, 'language', default='ru') + """ + data = await state.get_data() + + if key is None: + return data + + return data.get(key, default) + + +async def set_state_data( + state: FSMContext, + key: str, + value: Any +) -> None: + """ + Устанавливает данные в FSM состояние. + + Args: + state: Контекст FSM + key: Ключ + value: Значение + + Example: + >> await set_state_data(state, 'user_id', 123456789) + """ + await state.update_data(**{key: value}) + + +async def update_state_data( + state: FSMContext, + **kwargs +) -> None: + """ + Обновляет несколько полей в FSM состоянии. + + Args: + state: Контекст FSM + **kwargs: Пары ключ-значение для обновления + + Example: + >> await update_state_data( + ... state, + ... user_id=123456789, + ... language='ru', + ... step=1 + ... ) + """ + await state.update_data(**kwargs) + + +async def is_state_active(state: FSMContext) -> bool: + """ + Проверяет, активно ли какое-либо состояние. + + Args: + state: Контекст FSM + + Returns: + bool: True если есть активное состояние + + Example: + >> if await is_state_active(state): + ... await message.answer("У вас есть незавершенное действие") + """ + current_state = await state.get_state() + return current_state is not None + + +# ================= РАБОТА С CALLBACK QUERIES ================= + +async def answer_callback( + callback: CallbackQuery, + text: Optional[str] = None, + show_alert: bool = False, + cache_time: int = 0 +) -> bool: + """ + Отвечает на callback query. + + Args: + callback: Callback query + text: Текст уведомления + show_alert: Показать как alert + cache_time: Время кэширования + + Returns: + bool: True если успешно + + Example: + >> await answer_callback(callback, "✅ Готово!") + >> await answer_callback(callback, "⚠️ Ошибка", show_alert=True) + """ + try: + await callback.answer(text=text, show_alert=show_alert, cache_time=cache_time) + return True + except TelegramBadRequest as e: + logger.warning( + f"Не удалось ответить на callback: {e}", + log_type='CALLBACK' + ) + return False + + +async def safe_answer_callback( + callback: CallbackQuery, + text: Optional[str] = None, + show_alert: bool = False +) -> None: + """ + Безопасно отвечает на callback query (подавляет ошибки). + + Args: + callback: Callback query + text: Текст уведомления + show_alert: Показать как alert + + Example: + >> await safe_answer_callback(callback, "✅ Готово!") + """ + with suppress(TelegramBadRequest): + await callback.answer(text=text, show_alert=show_alert) + + +# ================= РАБОТА С СООБЩЕНИЯМИ ================= + +async def safe_delete_message( + message: Message, + log: bool = False +) -> bool: + """ + Безопасно удаляет сообщение. + + Args: + message: Сообщение для удаления + log: Логировать попытку удаления + + Returns: + bool: True если успешно удалено + + Example: + >> await safe_delete_message(message) + """ + try: + await message.delete() + + if log: + logger.debug( + f"Сообщение удалено: {message.message_id}", + log_type='MESSAGE' + ) + + return True + except TelegramBadRequest as e: + if log: + logger.warning( + f"Не удалось удалить сообщение: {e}", + log_type='MESSAGE' + ) + return False + + +async def safe_edit_message( + message: Message, + text: str, + **kwargs +) -> bool: + """ + Безопасно редактирует сообщение. + + Args: + message: Сообщение для редактирования + text: Новый текст + **kwargs: Дополнительные параметры (reply_markup, parse_mode, и т.д.) + + Returns: + bool: True если успешно отредактировано + + Example: + >> await safe_edit_message( + ... message, + ... "Новый текст", + ... parse_mode="HTML" + ... ) + """ + try: + await message.edit_text(text, **kwargs) + return True + except TelegramBadRequest as e: + logger.warning( + f"Не удалось отредактировать сообщение: {e}", + log_type='MESSAGE' + ) + return False + + +async def delete_messages( + chat_id: int, + message_ids: list[int], + bot +) -> int: + """ + Удаляет несколько сообщений. + + Args: + chat_id: ID чата + message_ids: Список ID сообщений + bot: Экземпляр бота + + Returns: + int: Количество успешно удаленных сообщений + + Example: + >> deleted = await delete_messages( + ... chat_id=message.chat.id, + ... message_ids=[123, 124, 125], + ... bot=bot + ... ) + >> print(f"Удалено {deleted} сообщений") + """ + deleted_count = 0 + + for message_id in message_ids: + try: + await bot.delete_message(chat_id=chat_id, message_id=message_id) + deleted_count += 1 + except TelegramBadRequest: + pass + + return deleted_count + + +# ================= КОМБИНИРОВАННЫЕ ФУНКЦИИ ================= + +async def inline_clear(update: Union[Message, CallbackQuery]) -> None: + """ + Очищает все инлайн взаимодействия (отвечает на callback). + + Args: + update: Объект обновления (Message или CallbackQuery) + + Example: + >> await inline_clear(callback) + """ + if isinstance(update, CallbackQuery): + await safe_answer_callback(update) + + +async def status_clear( + update: Union[Message, CallbackQuery], + state: FSMContext, + keep_data: Optional[Set[str]] = None, + remove_keyboard: bool = False +) -> None: + """ + Полная очистка: состояние FSM + ответ на callback + удаление клавиатуры. + + Args: + update: Объект обновления + state: Контекст FSM + keep_data: Данные для сохранения + remove_keyboard: Удалить клавиатуру (только для Message) + + Example: + >> # Полная очистка + >> await status_clear(message, state) + + >> # С сохранением данных + >> await status_clear( + ... callback, + ... state, + ... keep_data={'user_id', 'language'} + ... ) + + >> # С удалением клавиатуры + >> await status_clear(message, state, remove_keyboard=True) + """ + # Очищаем состояние + if keep_data: + await clear_state_keep_data(state, keep_keys=keep_data) + else: + await clear_state(state, log=True) + + # Отвечаем на callback + await inline_clear(update) + + # Удаляем клавиатуру если нужно + if remove_keyboard and isinstance(update, Message): + with suppress(TelegramBadRequest): + await update.answer( + "Отменено", + reply_markup=ReplyKeyboardRemove() + ) + + +# ================= УТИЛИТЫ ДЛЯ РАБОТЫ С СОСТОЯНИЯМИ ================= + +async def set_state_with_data( + state: FSMContext, + new_state: State, + **data +) -> None: + """ + Устанавливает новое состояние и данные одновременно. + + Args: + state: Контекст FSM + new_state: Новое состояние + **data: Данные для сохранения + + Example: + >> await set_state_with_data( + ... state, + ... FormStates.waiting_name, + ... user_id=123456789, + ... step=1 + ... ) + """ + await state.set_state(new_state) + if data: + await state.update_data(**data) + + logger.debug( + f"Установлено состояние: {new_state.state}", + log_type='FSM' + ) + + +async def get_or_create_data( + state: FSMContext, + key: str, + factory: Any +) -> Any: + """ + Получает данные из состояния или создает их если их нет. + + Args: + state: Контекст FSM + key: Ключ данных + factory: Значение по умолчанию или функция для создания + + Returns: + Any: Данные из состояния или созданные + + Example: + >> # С простым значением + >> items = await get_or_create_data(state, 'items', []) + + >> # С функцией + >> data = await get_or_create_data(state, 'data', lambda: {'count': 0}) + """ + data = await state.get_data() + + if key not in data: + # Создаем значение + if callable(factory): + value = factory() + else: + value = factory + + await state.update_data(**{key: value}) + return value + + return data[key] + + +async def increment_state_value( + state: FSMContext, + key: str, + amount: int = 1 +) -> int: + """ + Инкрементирует числовое значение в состоянии. + + Args: + state: Контекст FSM + key: Ключ значения + amount: Величина инкремента + + Returns: + int: Новое значение + + Example: + >> # Увеличиваем счетчик + >> new_count = await increment_state_value(state, 'attempts') + >> if new_count >= 3: + ... await message.answer("Слишком много попыток!") + """ + data = await state.get_data() + current = data.get(key, 0) + new_value = current + amount + + await state.update_data(**{key: new_value}) + return new_value + + +async def append_to_state_list( + state: FSMContext, + key: str, + value: Any +) -> list: + """ + Добавляет значение в список в состоянии. + + Args: + state: Контекст FSM + key: Ключ списка + value: Значение для добавления + + Returns: + list: Обновленный список + + Example: + >> # Добавляем товар в корзину + >> cart = await append_to_state_list(state, 'cart', product_id) + >> await message.answer(f"В корзине {len(cart)} товаров") + """ + data = await state.get_data() + current_list = data.get(key, []) + + if not isinstance(current_list, list): + current_list = [] + + current_list.append(value) + await state.update_data(**{key: current_list}) + + return current_list + + +async def remove_from_state_list( + state: FSMContext, + key: str, + value: Any +) -> list: + """ + Удаляет значение из списка в состоянии. + + Args: + state: Контекст FSM + key: Ключ списка + value: Значение для удаления + + Returns: + list: Обновленный список + + Example: + >> # Удаляем товар из корзины + >> cart = await remove_from_state_list(state, 'cart', product_id) + """ + data = await state.get_data() + current_list = data.get(key, []) + + if isinstance(current_list, list) and value in current_list: + current_list.remove(value) + await state.update_data(**{key: current_list}) + + return current_list + + +async def toggle_state_flag( + state: FSMContext, + key: str +) -> bool: + """ + Переключает boolean флаг в состоянии. + + Args: + state: Контекст FSM + key: Ключ флага + + Returns: + bool: Новое значение флага + + Example: + >> # Переключаем режим + >> is_active = await toggle_state_flag(state, 'notifications') + >> await message.answer( + ... f"Уведомления: {'включены' if is_active else 'выключены'}" + ... ) + """ + data = await state.get_data() + current = data.get(key, False) + new_value = not current + + await state.update_data(**{key: new_value}) + return new_value + + +# ================= ОТЛАДКА ================= + +async def debug_state(state: FSMContext) -> str: + """ + Возвращает отладочную информацию о состоянии. + + Args: + state: Контекст FSM + + Returns: + str: Форматированная информация о состоянии + + Example: + >> debug_info = await debug_state(state) + >> print(debug_info) + """ + current_state = await state.get_state() + data = await state.get_data() + + lines = [ + "🔍 Debug FSM:\n", + f"📊 Состояние: {current_state or 'None'}\n", + f"📦 Данных: {len(data)}\n" + ] + + if data: + lines.append("\nДанные:") + for key, value in data.items(): + value_str = str(value) + if len(value_str) > 50: + value_str = value_str[:50] + "..." + lines.append(f"• {key}: {value_str}") + + return "\n".join(lines) diff --git a/bot/utils/type_message.py b/bot/utils/type_message.py new file mode 100644 index 0000000..4dec0aa --- /dev/null +++ b/bot/utils/type_message.py @@ -0,0 +1,613 @@ +""" +Утилиты для работы с типами контента и чатов +""" +from typing import Final, Optional, Dict, Any +from enum import Enum + +from aiogram.types import Message +from aiogram.enums import ContentType, ChatType + +__all__ = ( + 'CHAT_TYPES_RU', + 'CONTENT_TYPES_RU', + 'CONTENT_EMOJI', + 'get_chat_type', + 'get_content_type', + 'get_content_text', + 'get_content_emoji', + 'get_media_info', + 'has_media', + 'has_text', + 'format_content_info', + 'ContentCategory', + 'get_content_category', + 'is_private_chat', + 'is_group_chat', + 'is_channel', + 'type_msg', + 'type_chat' +) + +# ==================== КОНСТАНТЫ ==================== + +# Типы чатов на русском +CHAT_TYPES_RU: Final[Dict[str, str]] = { + ChatType.PRIVATE: "Личные сообщения", + ChatType.GROUP: "Группа", + ChatType.SUPERGROUP: "Супергруппа", + ChatType.CHANNEL: "Канал", + "private": "Личные сообщения", + "group": "Группа", + "supergroup": "Супергруппа", + "channel": "Канал", +} + +# Типы контента на русском +CONTENT_TYPES_RU: Final[Dict[str, str]] = { + # Текст и медиа + ContentType.TEXT: "Текст", + ContentType.ANIMATION: "GIF анимация", + ContentType.AUDIO: "Аудиофайл", + ContentType.DOCUMENT: "Документ", + ContentType.PHOTO: "Фотография", + ContentType.STICKER: "Стикер", + ContentType.VIDEO: "Видео", + ContentType.VIDEO_NOTE: "Видеосообщение", + ContentType.VOICE: "Голосовое сообщение", + + # Контакты и локации + ContentType.CONTACT: "Контакт", + ContentType.LOCATION: "Геолокация", + ContentType.VENUE: "Место на карте", + + # Игры и развлечения + ContentType.DICE: "Игральная кость", + ContentType.GAME: "Игра", + ContentType.POLL: "Опрос", + + # События чата + ContentType.NEW_CHAT_MEMBERS: "Новые участники", + ContentType.LEFT_CHAT_MEMBER: "Участник покинул чат", + ContentType.NEW_CHAT_TITLE: "Изменено название чата", + ContentType.NEW_CHAT_PHOTO: "Изменена аватарка чата", + ContentType.DELETE_CHAT_PHOTO: "Удалена аватарка чата", + ContentType.GROUP_CHAT_CREATED: "Группа создана", + ContentType.SUPERGROUP_CHAT_CREATED: "Супергруппа создана", + ContentType.CHANNEL_CHAT_CREATED: "Канал создан", + ContentType.MESSAGE_AUTO_DELETE_TIMER_CHANGED: "Изменён таймер автоудаления", + ContentType.MIGRATE_TO_CHAT_ID: "Миграция в супергруппу", + ContentType.MIGRATE_FROM_CHAT_ID: "Миграция из группы", + ContentType.PINNED_MESSAGE: "Закреплено сообщение", + + # Платежи + ContentType.INVOICE: "Счёт на оплату", + ContentType.SUCCESSFUL_PAYMENT: "Успешная оплата", + + # Другое + ContentType.CONNECTED_WEBSITE: "Подключён сайт", + ContentType.PASSPORT_DATA: "Данные Telegram Passport", + ContentType.PROXIMITY_ALERT_TRIGGERED: "Сработал алерт приближения", + + # Видеочаты + ContentType.VIDEO_CHAT_SCHEDULED: "Запланирован видеочат", + ContentType.VIDEO_CHAT_STARTED: "Начался видеочат", + ContentType.VIDEO_CHAT_ENDED: "Завершён видеочат", + ContentType.VIDEO_CHAT_PARTICIPANTS_INVITED: "Приглашены в видеочат", + + # Web App + ContentType.WEB_APP_DATA: "Данные Web App", + + # Форумы + ContentType.FORUM_TOPIC_CREATED: "Создана тема форума", + ContentType.FORUM_TOPIC_EDITED: "Изменена тема форума", + ContentType.FORUM_TOPIC_CLOSED: "Закрыта тема форума", + ContentType.FORUM_TOPIC_REOPENED: "Открыта тема форума", + ContentType.GENERAL_FORUM_TOPIC_HIDDEN: "Скрыта общая тема", + ContentType.GENERAL_FORUM_TOPIC_UNHIDDEN: "Показана общая тема", + + # Розыгрыши + ContentType.GIVEAWAY_CREATED: "Создан розыгрыш", + ContentType.GIVEAWAY: "Розыгрыш", + ContentType.GIVEAWAY_WINNERS: "Победители розыгрыша", + ContentType.GIVEAWAY_COMPLETED: "Завершён розыгрыш", + + # Истории и реакции + ContentType.STORY: "История", +} + +# Эмодзи для типов контента +CONTENT_EMOJI: Final[Dict[str, str]] = { + ContentType.TEXT: "💬", + ContentType.ANIMATION: "🎞️", + ContentType.AUDIO: "🎵", + ContentType.DOCUMENT: "📄", + ContentType.PHOTO: "📷", + ContentType.STICKER: "🎨", + ContentType.VIDEO: "🎥", + ContentType.VIDEO_NOTE: "🎬", + ContentType.VOICE: "🎤", + ContentType.CONTACT: "👤", + ContentType.LOCATION: "📍", + ContentType.VENUE: "🏢", + ContentType.DICE: "🎲", + ContentType.GAME: "🎮", + ContentType.POLL: "📊", + ContentType.INVOICE: "💰", + ContentType.SUCCESSFUL_PAYMENT: "✅", +} + + +class ContentCategory(str, Enum): + """Категории контента""" + TEXT = "text" # Текстовые сообщения + MEDIA = "media" # Медиа (фото, видео, и т.д.) + FILE = "file" # Файлы и документы + VOICE = "voice" # Голосовые сообщения + LOCATION = "location" # Локации и места + INTERACTION = "interaction" # Игры, опросы, кости + SERVICE = "service" # Служебные сообщения + PAYMENT = "payment" # Платежи + UNKNOWN = "unknown" # Неизвестный тип + + +# ==================== ОСНОВНЫЕ ФУНКЦИИ ==================== + +def get_chat_type(message: Message, russian: bool = True) -> str: + """ + Возвращает тип чата. + + Args: + message: Объект сообщения + russian: Вернуть на русском языке + + Returns: + str: Тип чата + + Example: + >>> get_chat_type(message) + 'Личные сообщения' + >>> get_chat_type(message, russian=False) + 'private' + """ + chat_type = message.chat.type + + if russian: + return CHAT_TYPES_RU.get(chat_type, f"Неизвестный тип ({chat_type})") + + return chat_type + + +def get_content_type(message: Message, russian: bool = True) -> str: + """ + Возвращает тип контента сообщения. + + Args: + message: Объект сообщения + russian: Вернуть на русском языке + + Returns: + str: Тип контента + + Example: + >>> get_content_type(message) + 'Фотография' + >>> get_content_type(message, russian=False) + 'photo' + """ + content_type = message.content_type + + if russian: + return CONTENT_TYPES_RU.get(content_type, f"Неизвестный тип ({content_type})") + + return content_type + + +def get_content_emoji(message: Message) -> str: + """ + Возвращает эмодзи для типа контента. + + Args: + message: Объект сообщения + + Returns: + str: Эмодзи + + Example: + >>> get_content_emoji(message) + '📷' + """ + return CONTENT_EMOJI.get(message.content_type, "📎") + + +def get_content_text(message: Message, max_length: Optional[int] = None) -> Optional[str]: + """ + Извлекает текст из сообщения (текст или caption). + + Args: + message: Объект сообщения + max_length: Максимальная длина текста (обрезает если больше) + + Returns: + Optional[str]: Текст сообщения или None + + Example: + >>> get_content_text(message) + 'Привет, мир!' + + >>> get_content_text(message) # Фото с подписью + 'Красивое фото' + + >>> get_content_text(message, max_length=10) + 'Привет,...' + """ + text = message.text or message.caption + + if text and max_length and len(text) > max_length: + return f"{text[:max_length]}..." + + return text + + +def has_media(message: Message) -> bool: + """ + Проверяет, содержит ли сообщение медиа. + + Args: + message: Объект сообщения + + Returns: + bool: True если есть медиа + + Example: + >>> has_media(message) + True + """ + media_types = { + ContentType.PHOTO, + ContentType.VIDEO, + ContentType.ANIMATION, + ContentType.AUDIO, + ContentType.VOICE, + ContentType.VIDEO_NOTE, + ContentType.DOCUMENT, + ContentType.STICKER + } + + return message.content_type in media_types + + +def has_text(message: Message) -> bool: + """ + Проверяет, есть ли в сообщении текст (или caption). + + Args: + message: Объект сообщения + + Returns: + bool: True если есть текст + + Example: + >>> has_text(message) + True + """ + return bool(message.text or message.caption) + + +# ==================== ДЕТАЛЬНАЯ ИНФОРМАЦИЯ О МЕДИА ==================== + +def get_media_info(message: Message) -> Dict[str, Any]: + """ + Возвращает детальную информацию о медиа в сообщении. + + Args: + message: Объект сообщения + + Returns: + Dict: Словарь с информацией о медиа + + Example: + >>> get_media_info(message) + { + 'type': 'photo', + 'type_ru': 'Фотография', + 'emoji': '📷', + 'has_caption': True, + 'caption': 'Красивое фото', + 'file_size': 123456, + 'file_size_mb': 0.12, + 'width': 1920, + 'height': 1080, + 'duration': None + } + """ + info = { + 'type': message.content_type, + 'type_ru': get_content_type(message), + 'emoji': get_content_emoji(message), + 'has_caption': bool(message.caption), + 'caption': message.caption, + 'has_text': bool(message.text), + 'text': message.text, + } + + # Фото + if message.photo: + largest_photo = max(message.photo, key=lambda p: p.file_size or 0) + info.update({ + 'file_id': largest_photo.file_id, + 'file_unique_id': largest_photo.file_unique_id, + 'file_size': largest_photo.file_size, + 'file_size_kb': round(largest_photo.file_size / 1024, 2) if largest_photo.file_size else None, + 'width': largest_photo.width, + 'height': largest_photo.height, + 'count': len(message.photo) # Количество размеров + }) + + # Видео + elif message.video: + info.update({ + 'file_id': message.video.file_id, + 'file_unique_id': message.video.file_unique_id, + 'file_size': message.video.file_size, + 'file_size_mb': round(message.video.file_size / (1024 * 1024), 2) if message.video.file_size else None, + 'width': message.video.width, + 'height': message.video.height, + 'duration': message.video.duration, + 'duration_formatted': _format_duration(message.video.duration) if message.video.duration else None, + 'mime_type': message.video.mime_type, + 'file_name': message.video.file_name + }) + + # Документ + elif message.document: + info.update({ + 'file_id': message.document.file_id, + 'file_unique_id': message.document.file_unique_id, + 'file_size': message.document.file_size, + 'file_size_mb': round(message.document.file_size / (1024 * 1024), + 2) if message.document.file_size else None, + 'file_name': message.document.file_name, + 'mime_type': message.document.mime_type + }) + + # Аудио + elif message.audio: + info.update({ + 'file_id': message.audio.file_id, + 'file_unique_id': message.audio.file_unique_id, + 'file_size': message.audio.file_size, + 'file_size_mb': round(message.audio.file_size / (1024 * 1024), 2) if message.audio.file_size else None, + 'duration': message.audio.duration, + 'duration_formatted': _format_duration(message.audio.duration) if message.audio.duration else None, + 'performer': message.audio.performer, + 'title': message.audio.title, + 'mime_type': message.audio.mime_type, + 'file_name': message.audio.file_name + }) + + # Голосовое сообщение + elif message.voice: + info.update({ + 'file_id': message.voice.file_id, + 'file_unique_id': message.voice.file_unique_id, + 'file_size': message.voice.file_size, + 'file_size_kb': round(message.voice.file_size / 1024, 2) if message.voice.file_size else None, + 'duration': message.voice.duration, + 'duration_formatted': _format_duration(message.voice.duration) if message.voice.duration else None, + 'mime_type': message.voice.mime_type + }) + + # Видеосообщение + elif message.video_note: + info.update({ + 'file_id': message.video_note.file_id, + 'file_unique_id': message.video_note.file_unique_id, + 'file_size': message.video_note.file_size, + 'file_size_kb': round(message.video_note.file_size / 1024, 2) if message.video_note.file_size else None, + 'duration': message.video_note.duration, + 'duration_formatted': _format_duration( + message.video_note.duration) if message.video_note.duration else None, + 'length': message.video_note.length # Диаметр + }) + + # Анимация (GIF) + elif message.animation: + info.update({ + 'file_id': message.animation.file_id, + 'file_unique_id': message.animation.file_unique_id, + 'file_size': message.animation.file_size, + 'file_size_mb': round(message.animation.file_size / (1024 * 1024), + 2) if message.animation.file_size else None, + 'width': message.animation.width, + 'height': message.animation.height, + 'duration': message.animation.duration, + 'duration_formatted': _format_duration(message.animation.duration) if message.animation.duration else None, + 'mime_type': message.animation.mime_type, + 'file_name': message.animation.file_name + }) + + # Стикер + elif message.sticker: + info.update({ + 'file_id': message.sticker.file_id, + 'file_unique_id': message.sticker.file_unique_id, + 'file_size': message.sticker.file_size, + 'width': message.sticker.width, + 'height': message.sticker.height, + 'is_animated': message.sticker.is_animated, + 'is_video': message.sticker.is_video, + 'emoji': message.sticker.emoji, + 'set_name': message.sticker.set_name + }) + + return info + + +def format_content_info(message: Message, include_text: bool = True, max_text_length: int = 50) -> str: + """ + Форматирует информацию о контенте в читаемую строку. + + Args: + message: Объект сообщения + include_text: Включать текст/caption в описание + max_text_length: Максимальная длина текста + + Returns: + str: Отформатированная строка + + Example: + >>> format_content_info(message) + '📷 Фотография (1920x1080, 123 KB) + "Красивое фото"' + + >>> format_content_info(message) + '🎥 Видео (1920x1080, 5.2 MB, 1:30) + "Смотрите это видео"' + """ + emoji = get_content_emoji(message) + content_type = get_content_type(message) + + parts = [f"{emoji} {content_type}"] + + # Добавляем детали медиа + if message.photo: + largest = max(message.photo, key=lambda p: p.file_size or 0) + size_kb = largest.file_size / 1024 if largest.file_size else 0 + parts.append(f"({largest.width}x{largest.height}, {size_kb:.1f} KB)") + + elif message.video: + size_mb = message.video.file_size / (1024 * 1024) if message.video.file_size else 0 + duration = _format_duration(message.video.duration) if message.video.duration else "?" + parts.append(f"({message.video.width}x{message.video.height}, {size_mb:.1f} MB, {duration})") + + elif message.document: + size_mb = message.document.file_size / (1024 * 1024) if message.document.file_size else 0 + file_name = message.document.file_name or "без имени" + parts.append(f'("{file_name}", {size_mb:.2f} MB)') + + elif message.audio: + duration = _format_duration(message.audio.duration) if message.audio.duration else "?" + title = message.audio.title or "без названия" + parts.append(f'("{title}", {duration})') + + elif message.voice: + duration = _format_duration(message.voice.duration) if message.voice.duration else "?" + parts.append(f"({duration})") + + elif message.video_note: + duration = _format_duration(message.video_note.duration) if message.video_note.duration else "?" + parts.append(f"({duration})") + + elif message.sticker: + emoji_text = message.sticker.emoji or "" + parts.append(f"({emoji_text})") + + # Добавляем текст/caption + if include_text: + text = get_content_text(message, max_length=max_text_length) + if text: + parts.append(f'+ "{text}"') + + return ' '.join(parts) + + +def get_content_category(message: Message) -> ContentCategory: + """ + Определяет категорию контента. + + Args: + message: Объект сообщения + + Returns: + ContentCategory: Категория контента + + Example: + >>> get_content_category(message) + ContentCategory.MEDIA + """ + content_type = message.content_type + + # Текст + if content_type == ContentType.TEXT: + return ContentCategory.TEXT + + # Медиа + if content_type in {ContentType.PHOTO, ContentType.VIDEO, ContentType.ANIMATION, ContentType.STICKER}: + return ContentCategory.MEDIA + + # Файлы + if content_type in {ContentType.DOCUMENT, ContentType.AUDIO}: + return ContentCategory.FILE + + # Голосовые + if content_type in {ContentType.VOICE, ContentType.VIDEO_NOTE}: + return ContentCategory.VOICE + + # Локации + if content_type in {ContentType.LOCATION, ContentType.VENUE}: + return ContentCategory.LOCATION + + # Интерактивные + if content_type in {ContentType.DICE, ContentType.GAME, ContentType.POLL}: + return ContentCategory.INTERACTION + + # Платежи + if content_type in {ContentType.INVOICE, ContentType.SUCCESSFUL_PAYMENT}: + return ContentCategory.PAYMENT + + # Служебные + if content_type in { + ContentType.NEW_CHAT_MEMBERS, + ContentType.LEFT_CHAT_MEMBER, + ContentType.NEW_CHAT_TITLE, + ContentType.PINNED_MESSAGE + }: + return ContentCategory.SERVICE + + return ContentCategory.UNKNOWN + + +# ==================== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ==================== + +def _format_duration(seconds: int) -> str: + """ + Форматирует длительность в читаемый вид. + + Args: + seconds: Длительность в секундах + + Returns: + str: Отформатированная строка (MM:SS или HH:MM:SS) + + Example: + >>> _format_duration(90) + '1:30' + >>> _format_duration(3661) + '1:01:01' + """ + hours = seconds // 3600 + minutes = (seconds % 3600) // 60 + secs = seconds % 60 + + if hours > 0: + return f"{hours}:{minutes:02d}:{secs:02d}" + else: + return f"{minutes}:{secs:02d}" + + +def is_private_chat(message: Message) -> bool: + """Проверяет, является ли чат личным""" + return message.chat.type == ChatType.PRIVATE + + +def is_group_chat(message: Message) -> bool: + """Проверяет, является ли чат группой""" + return message.chat.type in {ChatType.GROUP, ChatType.SUPERGROUP} + + +def is_channel(message: Message) -> bool: + """Проверяет, является ли чат каналом""" + return message.chat.type == ChatType.CHANNEL + + +# Алиасы для обратной совместимости +type_msg = get_content_type +type_chat = get_chat_type diff --git a/bot/utils/usernames.py b/bot/utils/usernames.py new file mode 100644 index 0000000..b2eff8c --- /dev/null +++ b/bot/utils/usernames.py @@ -0,0 +1,409 @@ +""" +Утилиты для работы с информацией о пользователях +""" +from typing import Optional, Union +from enum import Enum + +from aiogram.types import Message, CallbackQuery, User, InlineQuery, ChatMemberUpdated + +__all__ = ( + 'get_user_display_name', + 'get_user_mention', + 'get_user_id', + 'username', + 'format_user', + 'UserFormat', + 'is_bot', + 'has_username', + 'is_premium', + 'get_language_code', + 'compare_users', + 'get_user_info_dict' +) + + +class UserFormat(str, Enum): + """Форматы отображения пользователя""" + USERNAME = 'username' # @username или @id123 + FULL_NAME = 'full_name' # Имя Фамилия + MENTION = 'mention' # HTML mention + MENTION_MARKDOWN = 'markdown' # Markdown mention + FIRST_NAME = 'first_name' # Только имя + ID_ONLY = 'id' # Только ID + DETAILED = 'detailed' # @username (Имя Фамилия, ID: 123) + + +# Тип для всех событий с пользователем +EventType = Union[Message, CallbackQuery, InlineQuery, ChatMemberUpdated] + + +def _extract_user(event: EventType) -> Optional[User]: + """ + Извлекает объект User из события. + + Args: + event: Объект события + + Returns: + User или None + """ + if isinstance(event, (Message, CallbackQuery, InlineQuery)): + return event.from_user + elif isinstance(event, ChatMemberUpdated): + return event.from_user or event.new_chat_member.user + + return None + + +def get_user_display_name( + event: EventType, + default: str = "Unknown User" +) -> str: + """ + Возвращает отображаемое имя пользователя (Full Name). + + Args: + event: Объект события (Message, CallbackQuery, и т.д.) + default: Значение по умолчанию если пользователь не найден + + Returns: + str: Полное имя пользователя + + Example: + >> get_user_display_name(message) + 'John Doe' + >> get_user_display_name(message) + 'John' # Если нет фамилии + """ + user = _extract_user(event) + + if not user: + return default + + # Полное имя (приоритет) + if user.full_name: + return user.full_name + + # Только имя + if user.first_name: + return user.first_name + + # Username как запасной вариант + if user.username: + return f"@{user.username}" + + # ID как последний вариант + return f"User {user.id}" + + +def get_user_mention( + event: EventType, + parse_mode: str = 'HTML', + show_username: bool = False +) -> str: + """ + Возвращает упоминание пользователя (кликабельное). + + Args: + event: Объект события + parse_mode: Режим парсинга ('HTML' или 'Markdown') + show_username: Показывать username вместо имени + + Returns: + str: HTML/Markdown упоминание + + Example: + >> get_user_mention(message) + 'John Doe' + + >> get_user_mention(message, parse_mode='Markdown') + '[John Doe](tg://user?id=123456789)' + + >> get_user_mention(message, show_username=True) + '@johndoe' + """ + user = _extract_user(event) + + if not user: + return "Unknown User" + + # Определяем текст для отображения + if show_username and user.username: + display_text = f"@{user.username}" + else: + display_text = user.full_name or user.first_name or f"User {user.id}" + + # Формируем ссылку + user_link = f"tg://user?id={user.id}" + + if parse_mode.upper() == 'HTML': + return f'{display_text}' + elif parse_mode.upper() in ('MARKDOWN', 'MARKDOWNV2'): + # Экранируем специальные символы для Markdown + display_text = display_text.replace('[', '\\[').replace(']', '\\]') + return f'[{display_text}]({user_link})' + else: + return display_text + + +def get_user_id(event: EventType) -> Optional[int]: + """ + Возвращает ID пользователя. + + Args: + event: Объект события + + Returns: + int или None: ID пользователя + + Example: + >> get_user_id(message) + 123456789 + """ + user = _extract_user(event) + return user.id if user else None + + +def username( + event: EventType, + with_at: bool = True, + fallback_to_id: bool = True +) -> str: + """ + Возвращает username пользователя или ID если username отсутствует. + + Это основная функция для получения идентификатора пользователя + в формате @username или @id123. + + Args: + event: Объект события (Message, CallbackQuery, и т.д.) + with_at: Добавлять @ в начало + fallback_to_id: Использовать ID если нет username + + Returns: + str: Username или ID пользователя + + Raises: + ValueError: Если информация о пользователе отсутствует + + Example: + >> username(message) + '@johndoe' + + >> username(message) # Нет username + '@123456789' + + >> username(message, with_at=False) + 'johndoe' + + >> username(message, fallback_to_id=False) + '' # Если нет username + """ + user = _extract_user(event) + + if not user: + raise ValueError("Информация о пользователе отсутствует в событии") + + # Если есть username + if user.username: + return f"@{user.username}" if with_at else user.username + + # Fallback на ID + if fallback_to_id: + return f"@{user.id}" if with_at else str(user.id) + + # Если ничего нет + return "" + + +def format_user( + event: EventType, + format_type: UserFormat = UserFormat.USERNAME, + default: str = "@System" +) -> str: + """ + Универсальная функция форматирования пользователя. + + Args: + event: Объект события + format_type: Тип форматирования (из enum UserFormat) + default: Значение по умолчанию + + Returns: + str: Отформатированная информация о пользователе + + Example: + >> format_user(message, UserFormat.USERNAME) + '@johndoe' + + >> format_user(message, UserFormat.FULL_NAME) + 'John Doe' + + >> format_user(message, UserFormat.MENTION) + 'John Doe' + + >> format_user(message, UserFormat.DETAILED) + '@johndoe (John Doe, ID: 123456789)' + """ + user = _extract_user(event) + + if not user: + return default + + # USERNAME: @username или @id + if format_type == UserFormat.USERNAME: + if user.username: + return f"@{user.username}" + return f"@{user.id}" + + # FULL_NAME: Имя Фамилия + elif format_type == UserFormat.FULL_NAME: + return user.full_name or user.first_name or f"User {user.id}" + + # MENTION: HTML упоминание + elif format_type == UserFormat.MENTION: + display = user.full_name or user.first_name or f"User {user.id}" + return f'{display}' + + # MENTION_MARKDOWN: Markdown упоминание + elif format_type == UserFormat.MENTION_MARKDOWN: + display = user.full_name or user.first_name or f"User {user.id}" + display = display.replace('[', '\\[').replace(']', '\\]') + return f'[{display}](tg://user?id={user.id})' + + # FIRST_NAME: Только имя + elif format_type == UserFormat.FIRST_NAME: + return user.first_name or f"User {user.id}" + + # ID_ONLY: Только ID + elif format_type == UserFormat.ID_ONLY: + return str(user.id) + + # DETAILED: Подробная информация + elif format_type == UserFormat.DETAILED: + parts = [] + + # Username + if user.username: + parts.append(f"@{user.username}") + + # Full name + if user.full_name: + parts.append(f"({user.full_name}") + elif user.first_name: + parts.append(f"({user.first_name}") + + # ID + parts.append(f"ID: {user.id})") + + return ' '.join(parts) if parts else f"User {user.id}" + + # По умолчанию + return default + + +# ================= ДОПОЛНИТЕЛЬНЫЕ УТИЛИТЫ ================= + +def is_bot(event: EventType) -> bool: + """ + Проверяет, является ли пользователь ботом. + + Args: + event: Объект события + + Returns: + bool: True если бот + """ + user = _extract_user(event) + return user.is_bot if user else False + + +def has_username(event: EventType) -> bool: + """ + Проверяет, есть ли у пользователя username. + + Args: + event: Объект события + + Returns: + bool: True если есть username + """ + user = _extract_user(event) + return bool(user and user.username) + + +def is_premium(event: EventType) -> bool: + """ + Проверяет, есть ли у пользователя Telegram Premium. + + Args: + event: Объект события + + Returns: + bool: True если Premium + """ + user = _extract_user(event) + return user.is_premium if user else False + + +def get_language_code(event: EventType) -> Optional[str]: + """ + Возвращает код языка пользователя. + + Args: + event: Объект события + + Returns: + Optional[str]: Код языка ('ru', 'en', и т.д.) + """ + user = _extract_user(event) + return user.language_code if user else None + + +def compare_users(event1: EventType, event2: EventType) -> bool: + """ + Сравнивает двух пользователей по ID. + + Args: + event1: Первое событие + event2: Второе событие + + Returns: + bool: True если это один и тот же пользователь + """ + user1 = _extract_user(event1) + user2 = _extract_user(event2) + + if not user1 or not user2: + return False + + return user1.id == user2.id + + +def get_user_info_dict(event: EventType) -> dict: + """ + Возвращает всю информацию о пользователе в виде словаря. + + Args: + event: Объект события + + Returns: + dict: Словарь с информацией о пользователе + """ + user = _extract_user(event) + + if not user: + return {} + + return { + 'id': user.id, + 'username': user.username, + 'first_name': user.first_name, + 'last_name': user.last_name, + 'full_name': user.full_name, + 'is_bot': user.is_bot, + 'is_premium': user.is_premium, + 'language_code': user.language_code, + 'mention': get_user_mention(event), + 'display_name': get_user_display_name(event) + } diff --git a/configs/__init__.py b/configs/__init__.py new file mode 100644 index 0000000..5952572 --- /dev/null +++ b/configs/__init__.py @@ -0,0 +1,3 @@ +from .cmd_alias_list import * +from .config import * +from .mapping import * diff --git a/configs/cmd_alias_list.py b/configs/cmd_alias_list.py new file mode 100644 index 0000000..eff3c27 --- /dev/null +++ b/configs/cmd_alias_list.py @@ -0,0 +1,363 @@ +from typing import Final + +# Настройка экспорта в модули +__all__ = ("COMMANDS",) + +# Список команд по ключу +COMMANDS: Final[dict[str, list[str]]] = { + "start": [ + "start", "старт", "почати", # основные + "ыефке", "cnfhn", "gjxfnb", # раскладка + "st", "on", "вкл", # сокращения + ], + + "help": [ + "help", "помощь", "допомога", # основные + "рудз", "gjvjom", "ljgjvjuf", # раскладка + "h", "хелп", "?", # сокращения + ], + + "menu": [ + "menu", "меню", # основные + "vtym", "vtye", # раскладка + "m", "mn", # сокращения + ], + + "stats": [ + "stats", "статистика", "стат", # основные + "cnfnbcnbrf", "cnfn", "cns", # раскладка + "stat", "st", "s", # сокращения + ], + + # ==================== ДОБАВЛЕНИЕ ПОСТОЯННЫХ ==================== + + "addword": [ + "addword", "добавитьслово", # основные + "фввцщкв", "lj,fdbnmckjdj", # раскладка + "aw", "addw", "добслово", # сокращения + ], + + "addlemma": [ + "addlemma", "добавитьлемму", # основные + "фввдуььф", "lj,fdbnmktve", # раскладка + "al", "addl", "доблемму", # сокращения + ], + + "addpart": [ + "addpart", "добавитьчасть", # основные + "фввзфке", "lj,fdbnmxfcnm", # раскладка + "ap", "addp", "добчасть", # сокращения + ], + + # ==================== ДОБАВЛЕНИЕ ВРЕМЕННЫХ ==================== + + "addtempword": [ + "addtempword", "добавитьвремслово", # основные + "фввеуьзцщкв", "lj,fdbnmdhtvckjdj", # раскладка + "atw", "addtw", "темпслово", # сокращения + ], + + "addtemplemma": [ + "addtemplemma", "добавитьвремлемму", # основные + "фввеуьздуььф", "lj,fdbnmdhtvktve", # раскладка + "atl", "addtl", "темплемму", # сокращения + ], + + # ==================== ДОБАВЛЕНИЕ ИСКЛЮЧЕНИЙ ==================== + + "addexcept": [ + "addexcept", "добавитьисключение", # основные + "фввучсузе", "lj,fdbnmbcrkx", # раскладка + "axc", "addwhite", "искл", # сокращения + ], + + # ==================== УДАЛЕНИЕ ПОСТОЯННЫХ ==================== + + "remword": [ + "remword", "удалитьслово", # основные + "кутцщкв", "elfkbnmckjdj", # раскладка + "rw", "delword", "dw", "удслово", # сокращения + ], + + "remlemma": [ + "remlemma", "удалитьлемму", # основные + "кутдуььф", "elfkbnmktve", # раскладка + "rl", "dellemma", "dl", "удлемму", # сокращения + ], + + "rempart": [ + "rempart", "удалитьчасть", # основные + "кутзфке", "elfkbnmxfcnm", # раскладка + "rp", "delpart", "dp", "удчасть", # сокращения + ], + + # ==================== УДАЛЕНИЕ ВРЕМЕННЫХ ==================== + + "remtempword": [ + "remtempword", "удалитьвремслово", # основные + "кутеуьзцщкв", "elfkbnmdhtvckjdj", # раскладка + "rtw", "deltw", "удтемпслово", # сокращения + ], + + "remtemplemma": [ + "remtemplemma", "удалитьвремлемму", # основные + "кутеуьздуььф", "elfkbnmdhtvktve", # раскладка + "rtl", "deltl", "удтемплемму", # сокращения + ], + + # ==================== УДАЛЕНИЕ ИСКЛЮЧЕНИЙ ==================== + + "remexcept": [ + "remexcept", "удалитьисключение", # основные + "кутучсузе", "elfkbnmbcrkx", # раскладка + "rxc", "remwhite", "удискл", # сокращения + ], + + # ==================== КОНФЛИКТНЫЕ СЛОВА ==================== + + "addconflictword": [ + "addconflictword", "добавитьконфликт", # основные + "фввсщтакшсецщкв", "lj,fdbnmrjyakbrn", # раскладка + "acw", "addcw", "конфслово", # сокращения + ], + + "addconflictlemma": [ + "addconflictlemma", "добавитьконфлемму", # основные + "фввсщтакшседуььф", "lj,fdbnmrjyaktve", # раскладка + "acl", "addcl", "конфлемму", # сокращения + ], + + "remconflictword": [ + "remconflictword", "удалитьконфликт", # основные + "кутсщтакшсецщкв", "elfkbnmrjyakbrn", # раскладка + "rcw", "delcw", "удконфликт", # сокращения + ], + + "remconflictlemma": [ + "remconflictlemma", "удалитьконфлемму", # основные + "кутсщтakшседуььф", "elfkbnmrjyaktve", # раскладка + "rcl", "delcl", "удконфлемму", # сокращения + ], + + # ==================== РЕЖИМ АНТИКОНФЛИКТА ==================== + + "stopconflict": [ + "stopconflict", "стопконфликт", # основные + "cnjgsщтakшse", "cnjzrjyakbrn", # раскладка + "sconf", "sc", "стопконф", # сокращения + ], + + "unstopconflict": [ + "unstopconflict", "отменаконфликта", # основные + "eycnjgsщтakшse", "jnvtyf", # раскладка + "usconf", "usc", "откконф", # сокращения + ], + + "conflictstatus": [ + "conflictstatus", "статусконфликта", # основные + "сщтakшseыефnec", "cnfnec", # раскладка + "cstatus", "cs", "статконф", # сокращения + ], + + # ==================== РЕЖИМ ТИШИНЫ ==================== + + "silence": [ + "silence", "тишина", "мут", # основные + "ышдутсу", "nbibyf", "ven", # раскладка + "sil", "mute", "quiet", "тиш", # сокращения + ], + + "unsilence": [ + "unsilence", "отменатишины", # основные + "eтышдутсу", "jnvtyf", # раскладка + "unsil", "unmute", "откмут", # сокращения + ], + + "silencestatus": [ + "silencestatus", "статустишины", # основные + "ышдутсуыефnec", "cnfnec", # раскладка + "sstatus", "ss", "статтиш", # сокращения + ], + + "extend_silence": [ + "extend_silence", "продлитьтишину", # основные + "уче_ышдутсу", "ghjlkbnmnbibyet", # раскладка + "exsil", "exs", "продтиш", # сокращения + ], + + # ==================== АДМИНИСТРАТОРЫ ==================== + + "addadmin": [ + "addadmin", "добавитьадмина", # основные + "фввфвьшт", "lj,fdbnmflvbyf", # раскладка + "aa", "addadm", "добадм", # сокращения + ], + + "remadmin": [ + "remadmin", "удалитьадмина", # основные + "кутфвьшт", "elfkbnmflvbyf", # раскладка + "ra", "remadm", "deladmin", "удадм", # сокращения + ], + + "listadmins": [ + "listadmins", "списокадминов", # основные + "дшыефвьшты", "cgbcjrflvbyjd", # раскладка + "admins", "adm", "adminlist", "адм", # сокращения + ], + + "adminhelp": [ + "adminhelp", "помощьадмину", # основные + "фвьштрудз", "gjvjomflvbyt", # раскладка + "admhelp", "ah", "хелпадм", # сокращения + ], + + "checkadmin": [ + "checkadmin", "проверкаадмина", # основные + "сруслфвьшт", "ghjdthrf", # раскладка + "isadmin", "ca", "провадм", # сокращения + ], + + # ==================== ПРОСМОТР ==================== + + "list": [ + "listwords", "списокслов", # основные + "дшыецщквы", "cgbcjrckjd", # раскладка + "lw", "list", "дшые", "words", "слова", # сокращения + ], + + "listlemmas": [ + "listlemmas", "списоклемм", # основные + "дшыедуььфы", "cgbcjrktv", # раскладка + "ll", "lemmas", "леммы", # сокращения + ], + + "listparts": [ + "listparts", "списокчастей", # основные + "дшыезфкеы", "cgbcjrxfcntq", # раскладка + "lp", "parts", "части", # сокращения + ], + + "listexcept": [ + "listexcept", "списокисключений", # основные + "дшыеучсузе", "cgbcjrbcrkx", # раскладка + "lxc", "except", "white", "искл", # сокращения + ], + + "listconflict": [ + "listconflict", "списокконфликтов", # основные + "дшыесщтakшse", "cgbcjrrjyakbrnjd", # раскладка + "lc", "conflict", "конф", # сокращения + ], + + # ==================== СТАТИСТИКА ==================== + + "userstats": [ + "userstats", "статистикапользователя", # основные + "ecthыефnы", "cnfnbcnbrf", # раскладка + "ustat", "us", "статюзер", # сокращения + ], + + "resetstats": [ + "resetstats", "сброситьстат", # основные + "кыуеыефnы", "c,hjcbnm", # раскладка + "rstats", "clearstats", "сброс", # сокращения + ], + + # ==================== ИНФОРМАЦИЯ ==================== + + "id": [ + "id", "айди", "инфо", # основные + "шв", "fqlb", "byaj", # раскладка + "info", "me", "мои", # сокращения + ], + + "myid": [ + "myid", "мойайди", # основные + "ьншв", "vjqfqlb", # раскладка + "mid", "мид", # сокращения + ], + + "chatid": [ + "chatid", "айдичата", # основные + "срфешв", "fqlbxfnf", # раскладка + "cid", "чатид", # сокращения + ], + + # ==================== РЕПОРТЫ ==================== + + "report": [ + "report", "репорт", "жалоба", # основные + "кузщке", "htgjhn", ";fkj,f", # раскладка + "rep", "r", "жал", # сокращения + ], + + "reporthelp": [ + "reporthelp", "помощьрепорт", # основные + "кузщкерудз", "gjvjomhtgjhn", # раскладка + "rephelp", "rh", "хелпреп", # сокращения + ], + + "reportstats": [ + "reportstats", "статистикарепортов", # основные + "кузщкеыефnы", "cnfnbcnbrf", # раскладка + "rstat", "rs", "статреп", # сокращения + ], + + "checkreport": [ + "checkreport", "проверкарепорта", # основные + "сруслкузщке", "ghjdthrf", # раскладка + "crep", "cr", "провреп", # сокращения + ], + + "closereport": [ + "closereport", "закрытьрепорт", # основные + "сдщыукузщке", "pfrhsnm", # раскладка + "close", "cl", "закреп", # сокращения + ], + + "banreport": [ + "banreport", "забанитьрепорт", # основные + "фтшкузщке", "pf,fybnm", # раскладка + "banrep", "br", "банреп", # сокращения + ], + + # ==================== ЭМОДЗИ ==================== + + "emoji": [ + "emoji", "эмодзи", # основные + "уьщош", "'vjlpb", # раскладка + "em", "emj", "эм", # сокращения + ], + + "emojihelp": [ + "emojihelp", "помощьэмодзи", # основные + "уьщошрудз", "gjvjom'vjlpb", # раскладка + "emhelp", "emh", "хелпэм", # сокращения + ], + + # ==================== СИСТЕМНЫЕ ==================== + + "ping": [ + "ping", "пинг", # основные + "зштп", "gbyp", # раскладка + "p", "пн", # сокращения + ], + + "version": [ + "version", "версия", # основные + "дукышщт", "dthcbz", # раскладка + "ver", "v", "вер", # сокращения + ], + + "reload": [ + "reload", "перезагрузка", # основные + "кудщфв", "gthtpfuheprf", # раскладка + "rl", "restart", "рест", # сокращения + ], + + "logs": [ + "logs", "логи", # основные + "дщпы", "kjub", # раскладка + "log", "l", "лог", # сокращения + ], +} diff --git a/configs/config.py b/configs/config.py new file mode 100644 index 0000000..1f5af80 --- /dev/null +++ b/configs/config.py @@ -0,0 +1,224 @@ +from pathlib import Path +from urllib.parse import urlparse, ParseResult +from typing import Optional, Any +from secrets import token_urlsafe + +from pydantic import field_validator, model_validator +from pydantic_settings import BaseSettings, SettingsConfigDict +from aiogram.types import ChatAdministratorRights + + +class _Settings(BaseSettings): + """Настройки бота с комплексной валидацией""" + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + extra="ignore", + case_sensitive=False, + validate_default=True, + ) + + # ============== ОСНОВНЫЕ ПАРАМЕТРЫ ============== + # Токены бота + BOT_TOKEN: Optional[str] = None + + # Параметры сообщений + PARSE_MODE: str = "HTML" + PREFIX: str = "/!.&?" + + # Разрешения и логирование + BOT_EDIT: bool = False + START_INFO_CONSOLE: bool = True + START_INFO_TO_FILE: bool = True + LOG_CONSOLE: bool = True + LOG_FILE: bool = True + LOG_DIR: Path = Path('Logs') + LOG_FILE_INFO: Path = Path('bot_info.log') + LOG_ROTATION: str = '100 MB' + LOG_RETENTION: str = '7 days' + + # Вебхук + WEBHOOK: bool = False + SECRET_TOKEN: Optional[str] = '' + WEBHOOK_URL: Optional[str] = None + WEBAPP_HOST: str = "0.0.0.0" + WEBAPP_PORT: int = 3131 + LOG_LEVEL: str = "warning" + ACCES_LOG: bool = False + + # API ключи + API_KEY: Optional[str] = None + WEB_API_KEY: Optional[str] = None + WEATHER_API_KEY: Optional[str] = None + + # Идентификаторы + OWNER_ID: list[int] = [6751720805] + ADMIN_ID: list[int] = [] + ADMIN_CHAT_ID: int = 0 + + # Настройки бота + BOT_NAME: str = "Бот" + BOT_DESCRIPTION: Optional[str] = None + BOT_SHORT_DESCRIPTION: Optional[str] = None + + # Права администратора + ANONYMOUS: bool = False + MANAGE_CHAT: bool = True + CHANGE_INFO: bool = True + PROMOTE_MEMBERS: bool = True + RESTRICT_MEMBERS: bool = True + POST_MESSAGE: bool = True + MANAGE_TOPICS: bool = True + INVITE_USER: bool = True + DELETE_MESSAGES: bool = True + MANAGE_VIDEO_CHATS: bool = True + EDIT_MESSAGES: bool = True + PIN_MESSAGE: bool = True + POST_STORIES: bool = True + EDIT_STORIES: bool = True + DELETE_STORIES: bool = True + + # Настройки сообщений + DISABLE_NOTIFICATION: bool = False + PROTECT_CONTENT: bool = False + ALLOW_SENDING_WITHOUT_REPLY: bool = True + LINK_PREVIEW_IS_DISABLED: bool = False + LINK_PREVIEW_PREFER_SMALL_MEDIA: bool = False + LINK_PREVIEW_PREFER_LARGE_MEDIA: bool = True + LINK_PREVIEW_SHOW_ABOVE_TEXT: bool = True + SHOW_CAPTION_ABOVE_MEDIA: bool = False + + # улучшения + ANTI_SPAM: bool = True + + # ================= ВАЛИДАТОРЫ ================= + @field_validator('PARSE_MODE') + def validate_parse_mode(cls, v: str) -> str: + allowed_modes: set[str] = {"HTML", "Markdown", "MarkdownV2"} + if v not in allowed_modes: + raise ValueError(f"Недопустимый PARSE_MODE. Допустимые: {', '.join(allowed_modes)}") + return v + + @field_validator('PREFIX') + def validate_prefix(cls, v: str) -> str: + cleaned: str = ''.join(dict.fromkeys(v)) # Удаление дубликатов с сохранением порядка + if len(cleaned) < 1: + raise ValueError("PREFIX должен содержать хотя бы один символ") + return cleaned + + @field_validator('LOG_DIR', 'LOG_FILE_INFO', 'POSTS_DIR', mode='before') + def validate_paths(cls, v: Any) -> Path: + return Path(v) if isinstance(v, str) else v + + @field_validator('WEBHOOK_URL') + def validate_webhook_url(cls, v: Optional[str]) -> Optional[str]: + if v is None: + return v + parsed: ParseResult = urlparse(v) + if not all([parsed.scheme, parsed.netloc]): + raise ValueError("Некорректный URL вебхука") + if parsed.scheme != 'https': + raise ValueError("WEBHOOK_URL должен использовать HTTPS") + return v + + @field_validator('BOT_NAME') + def validate_non_empty(cls, v: str) -> str: + if not v.strip(): + raise ValueError("Поле не может быть пустым") + return v + + @model_validator(mode='after') + def validate_bot_token(self) -> "_Settings": + if not self.BOT_TOKEN: + raise ValueError("Требуется BOT_TOKEN для рабочего режима") + return self + + @model_validator(mode='after') + def validate_webhook_config(self) -> "_Settings": + if self.WEBHOOK and not self.WEBHOOK_URL: + raise ValueError("WEBHOOK_URL обязателен при включенном WEBHOOK") + + # ✅ Генерация SECRET_TOKEN если не установлен + if self.WEBHOOK and not self.SECRET_TOKEN: + self.SECRET_TOKEN = token_urlsafe(32) + + return self + + @model_validator(mode='after') + def validate_logging_paths(self) -> "_Settings": + if self.LOG_FILE: + self.LOG_DIR.mkdir(parents=True, exist_ok=True) + + # ✅ Создание директории для постов + if not self.POSTS_DIR.exists(): + self.POSTS_DIR.mkdir(parents=True, exist_ok=True) + + return self + + @model_validator(mode='after') + def set_dynamic_descriptions(self) -> "_Settings": + if self.BOT_DESCRIPTION is None: + self.BOT_DESCRIPTION = f"Ваш помощник в удивительные миры! Prod. by:『@verdise』" + if self.BOT_SHORT_DESCRIPTION is None: + self.BOT_SHORT_DESCRIPTION = f"Тех.поддержка: @verdise" + return self + + # ================= СВОЙСТВА ================= + + @property + def rights(self) -> ChatAdministratorRights: + """Права администратора бота""" + return ChatAdministratorRights( + is_anonymous=self.ANONYMOUS, + can_manage_chat=self.MANAGE_CHAT, + can_delete_messages=self.DELETE_MESSAGES, + can_manage_video_chats=self.MANAGE_VIDEO_CHATS, + can_restrict_members=self.RESTRICT_MEMBERS, + can_promote_members=self.PROMOTE_MEMBERS, + can_change_info=self.CHANGE_INFO, + can_invite_users=self.INVITE_USER, + can_post_stories=self.POST_STORIES, + can_edit_stories=self.EDIT_STORIES, + can_delete_stories=self.DELETE_STORIES, + can_post_messages=self.POST_MESSAGE, + can_edit_messages=self.EDIT_MESSAGES, + can_pin_messages=self.PIN_MESSAGE, + can_manage_topics=self.MANAGE_TOPICS, + ) + + @property + def active_bot_token(self) -> str: + """Активный токен бота в зависимости от режима""" + if not self.BOT_TOKEN: + raise ValueError("Активный токен бота отсутствует") + return self.BOT_TOKEN + + @property + def log_dir_absolute(self) -> Path: + """Абсолютный путь к директории логов""" + return self.LOG_DIR.absolute() + + @property + def super_admin_ids(self) -> set[int]: + """Множество ID суперадминов (для банвордов)""" + return set(self.OWNER_ID) + + +# ✅ Единственный экземпляр настроек +settings = _Settings() + +# ✅ ОПЦИОНАЛЬНО: Простые константы для обратной совместимости (без дублирования) +# Используются только для удобства импорта, но ссылаются на settings +BOT_TOKEN = settings.active_bot_token +ADMIN_CHAT_ID = settings.ADMIN_CHAT_ID +SUPER_ADMIN_IDS = settings.super_admin_ids +WORDS_FILE = settings.WORDS_FILE + +# Экспорт +__all__ = ( + 'settings', + 'BOT_TOKEN', + 'ADMIN_CHAT_ID', + 'SUPER_ADMIN_IDS', + 'WORDS_FILE', +) diff --git a/configs/mapping.py b/configs/mapping.py new file mode 100644 index 0000000..549df05 --- /dev/null +++ b/configs/mapping.py @@ -0,0 +1,163 @@ +""" +Словари для нормализации текста и замены символов +""" +from typing import Dict + +# Словарь замены латинских букв на кириллические (для обхода фильтров) +LATIN_TO_CYRILLIC: Dict[str, str] = { + 'a': 'а', 'A': 'А', + 'b': 'б', 'B': 'В', + 'c': 'с', 'C': 'С', + 'e': 'е', 'E': 'Е', + 'h': 'н', 'H': 'Н', + 'k': 'к', 'K': 'К', + 'm': 'м', 'M': 'М', + 'o': 'о', 'O': 'О', + 'p': 'р', 'P': 'Р', + 't': 'т', 'T': 'Т', + 'x': 'х', 'X': 'Х', + 'y': 'у', 'Y': 'У' +} + +# Словарь замены похожих кириллических букв (украинские, белорусские и т.д.) +CYRILLIC_NORMALIZE: Dict[str, str] = { + 'ґ': 'г', 'Ґ': 'Г', # украинское Ґ + 'є': 'е', 'Є': 'Е', # украинское Є + 'і': 'и', 'І': 'И', # украинское І + 'ї': 'и', 'Ї': 'И', # украинское Ї + 'ў': 'у', 'Ў': 'У', # белорусское Ў + 'ѐ': 'е', 'Ѐ': 'Е', # кириллица с грависом + 'ё': 'е', 'Ё': 'Е', # ё -> е для упрощения +} + +# Большой словарь Unicode-символов -> кириллица/латиница +UNICODE_MAP: Dict[str, str] = { + # === ЛАТИНСКИЕ БУКВЫ -> КИРИЛЛИЦА === + 'a': 'а', 'A': 'А', 'b': 'б', 'B': 'В', 'c': 'с', 'C': 'С', + 'd': 'д', 'D': 'Д', 'e': 'е', 'E': 'Е', 'f': 'ф', 'F': 'Ф', + 'g': 'г', 'G': 'Г', 'h': 'н', 'H': 'Н', 'i': 'и', 'I': 'И', + 'j': 'ж', 'J': 'Ж', 'k': 'к', 'K': 'К', 'l': 'л', 'L': 'Л', + 'm': 'м', 'M': 'М', 'n': 'н', 'N': 'Н', 'o': 'о', 'O': 'О', + 'p': 'р', 'P': 'Р', 'q': 'к', 'Q': 'К', 'r': 'р', 'R': 'Р', + 's': 'с', 'S': 'С', 't': 'т', 'T': 'Т', 'u': 'у', 'U': 'У', + 'v': 'в', 'V': 'В', 'w': 'ш', 'W': 'Ш', 'x': 'х', 'X': 'Х', + 'y': 'у', 'Y': 'У', 'z': 'з', 'Z': 'З', + + # === SMALL CAPS === + 'ᴀ': 'а', 'ʙ': 'б', 'ᴄ': 'с', 'ᴅ': 'д', 'ᴇ': 'е', 'ꜰ': 'ф', + 'ɢ': 'г', 'ʜ': 'н', 'ɪ': 'и', 'ᴊ': 'ж', 'ᴋ': 'к', 'ʟ': 'л', + 'ᴍ': 'м', 'ɴ': 'н', 'ᴏ': 'о', 'ᴘ': 'р', 'ꞯ': 'к', 'ʀ': 'р', + 'ꜱ': 's', 'ᴛ': 'т', 'ᴜ': 'у', 'ᴠ': 'в', 'ᴡ': 'ш', 'ʏ': 'у', 'ᴢ': 'з', + 'ᴦ': 'г', 'ᴧ': 'л', 'ʍ': 'м', 'ᴨ': 'п', 'ᴩ': 'р', 'ɸ': 'ф', 'ɯ': 'ш', + + # === ГРЕЧЕСКИЕ === + 'α': 'а', 'Α': 'А', 'β': 'б', 'Β': 'В', 'γ': 'г', 'Γ': 'Г', + 'δ': 'д', 'Δ': 'Д', 'ε': 'е', 'Ε': 'Е', 'ζ': 'з', 'Ζ': 'З', + 'η': 'н', 'Η': 'Н', 'θ': 'т', 'Θ': 'Т', 'ι': 'и', 'Ι': 'И', + 'κ': 'к', 'Κ': 'К', 'λ': 'л', 'Λ': 'Л', 'μ': 'м', 'Μ': 'М', + 'ν': 'н', 'Ν': 'Н', 'ξ': 'кс', 'Ξ': 'КС', 'ο': 'о', 'Ο': 'О', + 'π': 'п', 'Π': 'П', 'ρ': 'р', 'Ρ': 'Р', 'σ': 'с', 'Σ': 'С', + 'τ': 'т', 'Τ': 'Т', 'υ': 'у', 'Υ': 'У', 'φ': 'ф', 'Φ': 'Ф', + 'χ': 'х', 'Χ': 'Х', 'ψ': 'пс', 'Ψ': 'ПС', 'ω': 'о', 'Ω': 'О', + 'ύ': 'у', 'ϱ': 'р', 'ς': 'с', 'ϲ': 'с', 'ϕ': 'ф', 'ϰ': 'к', + 'ϻ': 'м', 'ϸ': 'ш', 'ϙ': 'к', 'ϝ': 'в', '϶': 'э', 'ʐ': 'з', + 'ʒ': 'ж', 'ʂ': 'ш', 'ʈ': 'т', 'ɳ': 'н', 'ɭ': 'л', 'ƙ': 'к', + 'ɼ': 'р', 'ʠ': 'к', 'ɩ': 'и', 'ʝ': 'ж', 'ɦ': 'х', 'ɠ': 'г', + 'ɗ': 'д', 'ɓ': 'б', 'ɞ': 'е', 'ƒ': 'ф', 'ɧ': 'х', 'ʑ': 'з', + 'ɱ': 'м', 'ƴ': 'у', 'ʌ': 'л', 'ƿ': 'р', 'ɾ': 'р', 'ɟ': 'ж', + 'ɥ': 'х', 'ɰ': 'м', 'ѕ': 'с', 'ѡ': 'ш', + + # === КОПТСКИЕ === + 'ⲁ': 'а', 'Ⲁ': 'А', 'ⳝ': 'б', 'Ⳝ': 'Б', 'ⲃ': 'в', 'Ⲃ': 'В', + 'ⲅ': 'г', 'Ⲅ': 'Г', 'ⲇ': 'д', 'Ⲇ': 'Д', 'ⲉ': 'е', 'Ⲉ': 'Е', + 'ⲯ': 'ж', 'Ⲯ': 'Ж', 'ⳅ': 'з', 'Ⳅ': 'З', 'ⲕ': 'к', 'Ⲕ': 'К', + 'ⲗ': 'л', 'Ⲗ': 'Л', 'ⲙ': 'м', 'Ⲙ': 'М', 'ⲏ': 'н', 'Ⲏ': 'Н', + 'ⲟ': 'о', 'Ⲟ': 'О', 'ⲡ': 'п', 'Ⲡ': 'П', 'ⲣ': 'р', 'Ⲣ': 'Р', + 'ⲥ': 'с', 'Ⲥ': 'С', 'ⲧ': 'т', 'Ⲧ': 'Т', 'ⲩ': 'у', 'Ⲩ': 'У', + 'ⲫ': 'ф', 'Ⲫ': 'Ф', 'ⲭ': 'х', 'Ⲭ': 'Х', 'ⳡ': 'ч', 'Ⳡ': 'Ч', + 'ⲱ': 'ш', 'Ⲱ': 'Ш', 'ⳃ': 'щ', 'Ⳃ': 'Щ', 'ⳗ': 'ж', 'Ⳗ': 'Ж', + 'ⳋ': 'г', 'Ⳋ': 'Г', 'ⳑ': 'л', 'Ⳑ': 'Л', 'ⲋ': 'с', 'Ⲋ': 'С', + 'ⳳ': 'в', 'Ⳳ': 'В', 'ⲍ': 'з', 'Ⲍ': 'З', 'ⲓ': 'и', 'Ⲓ': 'И', + 'ⲛ': 'н', 'Ⲛ': 'Н', 'Ⳙ': 'у', 'ⳙ': 'у', + + # === КИРИЛЛИЧЕСКИЕ СТИЛИЗОВАННЫЕ === + 'ѧ': 'а', 'ѣ': 'е', 'ґ': 'г', 'Ґ': 'Г', 'є': 'е', 'Є': 'Е', + 'ѫ': 'о', 'Ѫ': 'О', 'ӡ': 'з', 'Ӡ': 'З', 'џ': 'дж', 'Џ': 'ДЖ', + 'ӣ': 'и', 'Ӣ': 'И', 'ѳ': 'ф', 'Ѳ': 'Ф', 'ⱀ': 'н', 'ҁ': 'ч', + 'ѻ': 'о', 'Ѻ': 'О', 'ҵ': 'ц', 'Ҵ': 'Ц', 'ӌ': 'ч', 'Ӌ': 'Ч', + 'ѱ': 'пс', 'Ѱ': 'ПС', 'ƀ': 'б', 'ѥ': 'е', 'Ѥ': 'Е', + 'ᴙ': 'я', 'і': 'и', 'І': 'И', 'ї': 'и', 'Ї': 'И', + 'ў': 'у', 'Ў': 'У', 'ӷ': 'г', 'Ӷ': 'Г', 'ӄ': 'к', 'Ӄ': 'К', + 'ҁ': 'ч', 'Ҁ': 'Ч', 'ӽ': 'х', 'Ӽ': 'Х', 'ҕ': 'г', 'Ҕ': 'Г', + 'ѵ': 'в', 'Ѵ': 'В', 'ʯ': 'ч', 'ɜ': 'з', + + # === TAI THAM === + 'ᥲ': 'а', 'ᥱ': 'е', 'ᥙ': 'и', 'ᥔ': 'й', '᧘': 'л', 'ᥒ': 'н', + '᧐': 'о', 'ᥰ': 'п', 'ᥴ': 'с', '᥊': 'х', '᥎': 'в', 'ᥕ': 'ш', + 'ᤋ': 'з', 'ᤁ': 'з', 'ᥣ': 'л', 'ꤌ': 'а', 'ꤒ': 'б', 'ꤐ': 'в', + '꤅': 'д', 'ꤕ': 'е', 'ꤣ': 'и', '꤇': 'й', '꤀': 'о', 'ꤙ': 'п', + 'ꤍ': 'с', 'ꤟ': 'ч', '꤈': 'л', 'ꤤ': 'д', 'ꤖ': 'х', '꤯': 'ж', + 'ꤗ': 'х', '꤂': 'в', 'ꤘ': 'з', 'ꤎ': 'я', 'მ': 'м', + + # === СТАРЫЕ ИТАЛИЙСКИЕ === + '𐌀': 'А', '𐌁': 'В', '𐌂': 'С', '𐌄': 'Е', '𐌅': 'Ф', '𐌉': 'И', + '𐌊': 'К', '𐌋': 'Ж', '𐌑': 'М', '𐌏': 'О', '𐌐': 'Г', '𐌛': 'Р', + '𐌕': 'Т', '𐌖': 'В', '𐌗': 'Х', '𐌟': 'Ж', '𐌍': 'Й', '𐍔': 'У', + '𐌔': 'З', '𐌒': 'К', '𐌓': 'Я', '𐍃': 'С', '𐌴': 'Э', '𐍂': 'Р', + '𐌜': 'Ь', '𐌆': 'Ж', '𐍆': 'Ф', '𐌺': 'К', '𐌡': 'Л', '𐌌': 'М', + '𐌻': 'л', '𐌼': 'м', '𐌽': 'н', '𐌸': 'щ', '𐍅': 'у', '𐍉': 'я', + '𐌵': 'у', '𐋏': 'н', '𐠨': 'в', + + # === ДЕВАНАГАРИ И ПРОЧИЕ === + '𑀐': 'г', '𑀥': 'д', '𑀝': 'с', '𑀡': 'ж', '𑀗': 'с', '𑀱': 'т', + '𑀉': 'л', '𑀌': 'х', '𑀨': 'ь', 'ઠ': 'б', 'ਡ': 'з', 'ਘ': 'щ', + 'ੜ': 'р', '੮': 'т', 'ਜ': 'ж', 'ઞ': 'о', 'ʆ': 'ж', 'ʠ': 'к', + 'ക': 'к', 'ሏ': 'е', 'ይ': 'е', 'ሦ': 'ж', 'ን': 'з', 'ሀ': 'и', + 'ህ': 'х', 'ኸ': 'к', 'በ': 'м', 'ጠ': 'м', 'ዘ': 'н', 'ዐ': 'о', + 'ከ': 'к', 'የ': 'р', 'ር': 'с', 'ፐ': 'т', 'ነ': 'у', 'ዋ': 'ф', + 'ጰ': 'х', 'ሃ': 'ч', 'ሠ': 'ш', 'ሡ': 'щ', 'ፊ': 'ы', 'ሪ': 'ь', + 'ጓ': 'э', 'ሬ': 'ю', 'ጸ': 'я', 'ል': 'а', 'ፔ': 'б', 'ፎ': 'в', + 'ታ': 'г', 'ፑ': 'ф', 'ፘ': 'г', 'ፗ': 'ж', 'ጋ': 'ж', 'ረ': 'л', + 'ዓ': 'к', 'ዩ': 'р', 'ና': 'с', 'ሏ': 'д', 'ጠ': 'м', 'ፗ': 'ж', + 'ᱧ': 'к', 'ᱦ': 'ш', 'ຸ': 'у', 'ս': 'у', 'Ա': 'ч', 'Կ': 'ч', + 'Ꮁ': 'Г', 'Ꮾ': 'Б', 'Ꮶ': 'К', 'Ꮧ': 'Л', 'Ꮇ': 'М', 'Ꮋ': 'Н', + 'Ꮻ': 'О', 'Ꮲ': 'Р', 'Ꮯ': 'С', 'Ꭲ': 'Т', 'Ꭹ': 'У', 'Ꮱ': 'Ф', + 'Ꮞ': 'Ч', 'Ꮚ': 'Ш', 'Ꮗ': 'Щ', 'Ꭺ': 'А', 'Ꭰ': 'Д', 'Ꭼ': 'Е', + 'Ꮀ': 'Ф', 'Ꮐ': 'Г', 'Ꮖ': 'И', 'Ꭻ': 'Ж', 'Ꮮ': 'Л', 'Ꮢ': 'Р', + 'Ꮪ': 'С', 'Ꮜ': 'У', 'Ꮩ': 'В', 'Ꮃ': 'Ш', 'Ꮓ': 'З', 'Ꮐ': 'Г', + 'Ꭷ': 'К', 'Ꮀ': 'Х', 'Ᏼ': 'В', 'Ᏽ': 'Г', 'ᏏᏓ': 'Ы', 'Ꮟ': 'Ь', + 'ᎰᏫ': 'Ю', 'ᕒ': 'З', 'ᕈ': 'Р', 'ᑲ': 'Б', 'ᑯ': 'Д', 'ᴊ': 'Ж', + + # === FULLWIDTH === + 'a': 'а', 'b': 'б', 'c': 'с', 'd': 'д', 'e': 'е', 'f': 'ф', + 'g': 'г', 'h': 'н', 'i': 'и', 'j': 'ж', 'k': 'к', 'l': 'л', + 'm': 'м', 'n': 'н', 'o': 'о', 'p': 'р', 'q': 'к', 'r': 'р', + 's': 'с', 't': 'т', 'u': 'у', 'v': 'в', 'w': 'ш', 'x': 'х', + 'y': 'у', 'z': 'з', + + # === МАТЕМАТИЧЕСКИЕ === + '𝐚': 'а', '𝐛': 'б', '𝐜': 'с', '𝐝': 'д', '𝐞': 'е', '𝐟': 'ф', + '𝐠': 'г', '𝐡': 'н', '𝐢': 'и', '𝐣': 'ж', '𝐤': 'к', '𝐥': 'л', + '𝐦': 'м', '𝐧': 'н', '𝐨': 'о', '𝐩': 'р', '𝐪': 'к', '𝐫': 'р', + '𝐬': 'с', '𝐭': 'т', '𝐮': 'у', '𝐯': 'в', '𝐰': 'ш', '𝐱': 'х', + '𝐲': 'у', '𝐳': 'з', + + # === CIRCLED === + 'ⓐ': 'а', 'ⓑ': 'б', 'ⓒ': 'с', 'ⓓ': 'д', 'ⓔ': 'е', 'ⓕ': 'ф', + 'ⓖ': 'г', 'ⓗ': 'н', 'ⓘ': 'и', 'ⓙ': 'ж', 'ⓚ': 'к', 'ⓛ': 'л', + 'ⓜ': 'м', 'ⓝ': 'н', 'ⓞ': 'о', 'ⓟ': 'р', 'ⓠ': 'к', 'ⓡ': 'р', + 'ⓢ': 'с', 'ⓣ': 'т', 'ⓤ': 'у', 'ⓥ': 'в', 'ⓦ': 'ш', 'ⓧ': 'х', + 'ⓨ': 'у', 'ⓩ': 'з', + + # === GUJARATI/DEVANAGARI === + 'ુ': 'у', 'ૠ': 'р', '૦': 'о', 'વ': 'к', 'ઽ': 'с', 'પ': 'ч', + 'ક': 'к', '𑀋': 'х', 'ળ': 'я', 'ખ': 'ы', 'उ': 'з', 'چ': 'б', + 'ሩ': 'ю', 'ራ': 'ь', 'ል': 'а', 'ዓ': 'к', 'ዩ': 'р', 'ና': 'с', + '∂': 'д', '⨍': 'ф', 'ϻ': 'м', 'ጋ': 'ж', 'პ': 'п', 'ჰ': 'х', + 'Ͷ': 'М', 'Ͳ': 'Т', 'Ϸ': 'Р', 'Ϥ': 'Ч', 'Ͽ': 'Э', 'Ϳ': 'Ж', + 'Ɗ': 'Д', 'Ɠ': 'Г', 'Ɍ': 'Р', 'Ʋ': 'У', 'Ɲ': 'Н', 'Ϙ': 'К', + 'ϒ': 'У', 'ζ': 'з', 'Ŵ': 'Ш', '℔': 'Ы', 'ሃ': 'х', + + # === ЦИФРЫ КАК БУКВЫ === + '0': 'о', '1': 'и', '3': 'з', '4': 'ч', '5': 'с', '7': 'т', '8': 'в', +} diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000..3ef18cf --- /dev/null +++ b/database/__init__.py @@ -0,0 +1,39 @@ +""" +Database модуль для работы с банвордами в SQLite. + +Использует SQLAlchemy ORM для async работы с БД. + +Структура: +- models.py: Модели таблиц (BanWord, TempBanWord, WhitelistWord, Admin, Setting, SpamStat) +- database.py: Подключение к БД через SQLAlchemy +- repository.py: CRUD операции через ORM +- manager.py: Высокоуровневый API для handlers/middleware + +Usage: + from database import get_manager, BanWordType + + # Инициализация + manager = get_manager() + await manager.init() + + # Добавление банворда + await manager.add_banword("спам", BanWordType.SUBSTRING, added_by=123) + + # Проверка (из кэша - быстро) + words = manager.get_banwords_cached(BanWordType.SUBSTRING) + if "спам" in text and "спам" in words: + await manager.log_spam(...) + + # Режим тишины + await manager.set_silence_mode(minutes=30) + if await manager.is_silence_active(): + # Удаляем всё +""" + +from .models import * + +from .database import * + +from .repository import * + +from .manager import * diff --git a/database/database.py b/database/database.py new file mode 100644 index 0000000..4198491 --- /dev/null +++ b/database/database.py @@ -0,0 +1,115 @@ +""" +Управление SQLAlchemy движком и сессиями. +""" +from pathlib import Path +from typing import AsyncGenerator + +from sqlalchemy.ext.asyncio import ( + create_async_engine, + async_sessionmaker, + AsyncSession, + AsyncEngine +) + +from middleware.loggers import logger +from .models import Base + +__all__ = ("Database", "get_db") + + +class Database: + """ + Менеджер SQLAlchemy базы данных. + + Attributes: + engine: Async движок SQLAlchemy + session_factory: Фабрика сессий + """ + + def __init__(self, db_path: str = "banwords.db"): + """ + Args: + db_path: Путь к SQLite файлу + """ + # Создаём директорию если не существует + db_file = Path(db_path) + db_file.parent.mkdir(parents=True, exist_ok=True) + + # SQLite URL для async + db_url = f"sqlite+aiosqlite:///{db_path}" + + # Создаём async движок + self.engine: AsyncEngine = create_async_engine( + db_url, + echo=False, # Логирование SQL запросов (False для прода) + future=True, + pool_pre_ping=True, # Проверка соединения + ) + + # Фабрика сессий + self.session_factory = async_sessionmaker( + self.engine, + class_=AsyncSession, + expire_on_commit=False, + ) + + logger.info( + f"SQLAlchemy инициализирован: {db_path}", + log_type="DATABASE" + ) + + async def init(self) -> None: + """Создаёт все таблицы в БД""" + try: + async with self.engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + + logger.info( + "Таблицы базы данных созданы", + log_type="DATABASE" + ) + except Exception as e: + logger.error( + f"Ошибка создания таблиц: {e}", + log_type="DATABASE" + ) + raise + + async def close(self) -> None: + """Закрывает соединения с БД""" + await self.engine.dispose() + logger.info("База данных закрыта", log_type="DATABASE") + + def get_session(self) -> AsyncGenerator[AsyncSession, None]: + """ + Создаёт новую сессию (контекстный менеджер). + + Usage: + async with db.get_session() as session: + result = await session.execute(select(BanWord)) + words = result.scalars().all() + + Yields: + AsyncSession: Сессия для работы с БД + """ + return self.session_factory() + + +# Глобальный экземпляр +_db_instance: Database | None = None + + +def get_db(db_path: str = "banwords.db") -> Database: + """ + Возвращает глобальный экземпляр Database (Singleton). + + Args: + db_path: Путь к БД (используется только при первом вызове) + + Returns: + Database: Экземпляр базы данных + """ + global _db_instance + if _db_instance is None: + _db_instance = Database(db_path) + return _db_instance diff --git a/database/manager.py b/database/manager.py new file mode 100644 index 0000000..1a98295 --- /dev/null +++ b/database/manager.py @@ -0,0 +1,582 @@ +""" +Высокоуровневый менеджер для работы с банвордами. +Упрощает использование repository в handlers и middleware. +""" +from typing import Set, Optional, List, Dict, Any +from datetime import datetime + +from middleware.loggers import logger +from .database import Database, get_db +from .repository import BanWordsRepository +from .models import BanWordType, SpamStat, SpamLog + +from sqlalchemy import select, delete, func, desc + +__all__ = ("BanWordsManager", "get_manager") + + +class BanWordsManager: + """ + Менеджер для удобной работы с банвордами. + + Предоставляет упрощённый API для handlers и middleware. + + Attributes: + db: Экземпляр Database + repo: Repository для CRUD операций + """ + + def __init__(self, db: Optional[Database] = None): + """ + Args: + db: Экземпляр Database (если None, берётся глобальный) + """ + self.db = db or get_db() + self.repo = BanWordsRepository(self.db) + + # Кэш для часто используемых данных + self._cache_banwords: Optional[dict] = None + self._cache_whitelist: Optional[Set[str]] = None + self._cache_admins: Optional[Set[int]] = None + self._cache_updated_at: Optional[datetime] = None + + async def init(self) -> None: + """Инициализирует базу данных и загружает кэш""" + await self.db.init() + await self.refresh_cache() + logger.info("BanWordsManager инициализирован", log_type="DATABASE") + + async def close(self) -> None: + """Закрывает соединение с БД""" + await self.db.close() + + # === CACHE MANAGEMENT === + + async def refresh_cache(self) -> None: + """Обновляет кэш из БД""" + try: + self._cache_banwords = await self.repo.get_all_banwords() + temp_banwords = await self.repo.get_all_temp_banwords() + + # Объединяем постоянные и временные банворды + for word_type, words in temp_banwords.items(): + if word_type in self._cache_banwords: + self._cache_banwords[word_type] |= words + + self._cache_whitelist = await self.repo.get_whitelist() + self._cache_admins = await self.repo.get_admins() + self._cache_updated_at = datetime.now() + + logger.debug("Кэш банвордов обновлён", log_type="DATABASE") + + except Exception as e: + logger.error(f"Ошибка обновления кэша: {e}", log_type="DATABASE") + + def invalidate_cache(self) -> None: + """Сбрасывает кэш (требует refresh_cache)""" + self._cache_banwords = None + self._cache_whitelist = None + self._cache_admins = None + self._cache_updated_at = None + + # === BANWORDS (с кэшем) === + + async def add_banword( + self, + word: str, + word_type: BanWordType, + added_by: Optional[int] = None, + reason: Optional[str] = None, + refresh_cache: bool = True + ) -> bool: + """ + Добавляет банворд и обновляет кэш. + + Args: + word: Слово + word_type: Тип + added_by: ID админа + reason: Причина + refresh_cache: Обновить кэш после добавления + + Returns: + bool: True если добавлен + """ + result = await self.repo.add_banword(word, word_type, added_by, reason) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + async def remove_banword( + self, + word: str, + word_type: BanWordType, + refresh_cache: bool = True + ) -> bool: + """Удаляет банворд и обновляет кэш""" + result = await self.repo.remove_banword(word, word_type) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + def get_banwords_cached(self, word_type: BanWordType) -> Set[str]: + """ + Получает банворды из кэша (быстро). + + Args: + word_type: Тип банвордов + + Returns: + Set[str]: Набор слов из кэша + """ + if self._cache_banwords is None: + logger.warning("Кэш не инициализирован", log_type="DATABASE") + return set() + + return self._cache_banwords.get(word_type, set()) + + async def get_banwords(self, word_type: BanWordType) -> Set[str]: + """Получает банворды напрямую из БД (без кэша)""" + return await self.repo.get_banwords(word_type) + + # === TEMPORARY BANWORDS === + + async def add_temp_banword( + self, + word: str, + word_type: BanWordType, + minutes: int, + added_by: Optional[int] = None, + refresh_cache: bool = True + ) -> bool: + """Добавляет временный банворд""" + result = await self.repo.add_temp_banword( + word, word_type, minutes, added_by + ) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + async def remove_temp_banword( + self, + word: str, + word_type: BanWordType, + refresh_cache: bool = True + ) -> bool: + """Удаляет временный банворд""" + result = await self.repo.remove_temp_banword(word, word_type) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + async def cleanup_expired(self) -> int: + """ + Очищает истёкшие временные банворды. + Вызывается периодически (например, раз в минуту). + + Returns: + int: Количество удалённых записей + """ + deleted = await self.repo.cleanup_expired_temp_banwords() + + if deleted > 0: + await self.refresh_cache() + + return deleted + + # === WHITELIST === + + async def add_whitelist( + self, + word: str, + added_by: Optional[int] = None, + reason: Optional[str] = None, + refresh_cache: bool = True + ) -> bool: + """Добавляет слово в белый список""" + result = await self.repo.add_whitelist(word, added_by, reason) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + async def remove_whitelist( + self, + word: str, + refresh_cache: bool = True + ) -> bool: + """Удаляет слово из белого списка""" + result = await self.repo.remove_whitelist(word) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + def get_whitelist_cached(self) -> Set[str]: + """Получает белый список из кэша""" + if self._cache_whitelist is None: + logger.warning("Кэш whitelist не инициализирован", log_type="DATABASE") + return set() + + return self._cache_whitelist + + def is_whitelisted(self, text: str) -> bool: + """ + Проверяет, содержит ли текст слово из белого списка. + + Args: + text: Текст для проверки (lowercase) + + Returns: + bool: True если найдено исключение + """ + whitelist = self.get_whitelist_cached() + return any(word in text for word in whitelist) + + # === ADMINS === + + async def add_admin( + self, + user_id: int, + added_by: Optional[int] = None, + refresh_cache: bool = True + ) -> bool: + """Добавляет администратора""" + result = await self.repo.add_admin(user_id, added_by) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + async def remove_admin( + self, + user_id: int, + refresh_cache: bool = True + ) -> bool: + """Удаляет администратора""" + result = await self.repo.remove_admin(user_id) + + if result and refresh_cache: + await self.refresh_cache() + + return result + + def get_admins_cached(self) -> Set[int]: + """Получает список админов из кэша""" + if self._cache_admins is None: + logger.warning("Кэш админов не инициализирован", log_type="DATABASE") + return set() + + return self._cache_admins + + def is_admin_cached(self, user_id: int) -> bool: + """ + Проверяет, является ли пользователь админом (из кэша). + + Args: + user_id: Telegram ID + + Returns: + bool: True если админ + """ + return user_id in self.get_admins_cached() + + async def is_admin(self, user_id: int) -> bool: + """Проверяет админа напрямую из БД""" + return await self.repo.is_admin(user_id) + + # === SETTINGS (режимы silence/conflict) === + + async def set_silence_mode(self, minutes: int) -> datetime: + """ + Включает режим тишины на указанное время. + + Args: + minutes: Длительность в минутах + + Returns: + datetime: Время окончания режима + """ + expires_at = datetime.now().timestamp() + (minutes * 60) + await self.repo.set_setting("silence_until", str(expires_at)) + + logger.info( + f"Режим тишины активирован на {minutes} мин", + log_type="SILENCE" + ) + + return datetime.fromtimestamp(expires_at) + + async def disable_silence_mode(self) -> None: + """Отключает режим тишины""" + await self.repo.delete_setting("silence_until") + logger.info("Режим тишины отключён", log_type="SILENCE") + + async def is_silence_active(self) -> bool: + """Проверяет, активен ли режим тишины""" + silence_until_str = await self.repo.get_setting("silence_until") + + if not silence_until_str: + return False + + try: + silence_until = float(silence_until_str) + now = datetime.now().timestamp() + + if now >= silence_until: + # Время истекло - удаляем настройку + await self.disable_silence_mode() + return False + + return True + + except (ValueError, TypeError): + return False + + async def set_conflict_mode(self, minutes: int) -> datetime: + """ + Включает режим антиконфликта на указанное время. + + Args: + minutes: Длительность в минутах + + Returns: + datetime: Время окончания режима + """ + expires_at = datetime.now().timestamp() + (minutes * 60) + await self.repo.set_setting("conflict_until", str(expires_at)) + + logger.info( + f"Режим антиконфликта активирован на {minutes} мин", + log_type="CONFLICT" + ) + + return datetime.fromtimestamp(expires_at) + + async def disable_conflict_mode(self) -> None: + """Отключает режим антиконфликта""" + await self.repo.delete_setting("conflict_until") + logger.info("Режим антиконфликта отключён", log_type="CONFLICT") + + async def is_conflict_active(self) -> bool: + """Проверяет, активен ли режим антиконфликта""" + conflict_until_str = await self.repo.get_setting("conflict_until") + + if not conflict_until_str: + return False + + try: + conflict_until = float(conflict_until_str) + now = datetime.now().timestamp() + + if now >= conflict_until: + # Время истекло + await self.disable_conflict_mode() + return False + + return True + + except (ValueError, TypeError): + return False + + # === STATISTICS === + + async def log_spam( + self, + user_id: int, + username: str, + chat_id: int, + message_text: str, + matched_word: str, + match_type: str + ) -> None: + """Логирует удаление спам-сообщения""" + await self.repo.log_spam_deletion( + user_id=user_id, + username=username, + chat_id=chat_id, + message_text=message_text, + matched_word=matched_word, + match_type=match_type + ) + + async def get_spam_stats( + self, + limit: int = 100, + user_id: Optional[int] = None + ) -> List[SpamStat]: + """Получает статистику удалений""" + return await self.repo.get_spam_stats(limit, user_id) + + async def get_user_spam_count(self, user_id: int) -> int: + """Получает количество удалённых сообщений пользователя""" + return await self.repo.get_user_spam_count(user_id) + + async def get_top_spammers(self, limit: int = 10) -> List[tuple[int, int]]: + """Получает топ спамеров""" + return await self.repo.get_top_spammers(limit) + + # === INFO === + + async def get_stats(self) -> dict: + """Получает общую статистику""" + db_stats = await self.repo.get_stats() + + # Добавляем информацию о кэше + cache_info = { + 'cache_active': self._cache_banwords is not None, + 'cache_updated_at': self._cache_updated_at.isoformat() if self._cache_updated_at else None + } + + return {**db_stats, **cache_info} + + async def get_all_words_list(self) -> dict: + """ + Получает все слова для команды /listwords. + + Returns: + dict: Словарь со всеми категориями слов + """ + banwords = await self.repo.get_all_banwords() + temp_banwords = await self.repo.get_all_temp_banwords() + whitelist = await self.repo.get_whitelist() + admins = await self.repo.get_admins() + + return { + 'substring': banwords.get(BanWordType.SUBSTRING, set()), + 'lemma': banwords.get(BanWordType.LEMMA, set()), + 'part': banwords.get(BanWordType.PART, set()), + 'conflict_substring': banwords.get(BanWordType.CONFLICT_SUBSTRING, set()), + 'conflict_lemma': banwords.get(BanWordType.CONFLICT_LEMMA, set()), + 'temp_substring': temp_banwords.get(BanWordType.SUBSTRING, set()), + 'temp_lemma': temp_banwords.get(BanWordType.LEMMA, set()), + 'whitelist': whitelist, + 'admins': admins + } + + async def get_top_words(self, limit: int = 10) -> List[Dict[str, Any]]: + """ + Получает топ N самых часто срабатывающих слов. + + Args: + limit: Количество слов в топе + + Returns: + List[Dict]: Список словарей с данными: + - word: слово + - count: количество срабатываний + - type: тип проверки + """ + async with self.session_maker() as session: + try: + # Группируем по matched_word и считаем количество + query = select( + SpamLog.matched_word, + SpamLog.match_type, + func.count(SpamLog.id).label('count') + ).where( + SpamLog.matched_word.isnot(None) + ).group_by( + SpamLog.matched_word, + SpamLog.match_type + ).order_by( + desc('count') + ).limit(limit) + + result = await session.execute(query) + rows = result.all() + + # Форматируем результат + top_words = [] + for row in rows: + top_words.append({ + 'word': row.matched_word, + 'type': row.match_type, + 'count': row.count + }) + + logger.debug( + f"Получен топ-{limit} слов: {len(top_words)} записей", + log_type="DATABASE" + ) + + return top_words + + except Exception as e: + logger.error( + f"Ошибка получения топ-слов: {e}", + log_type="DATABASE" + ) + return [] + + async def get_total_spam_count(self) -> int: + """ + Получает общее количество удалённых сообщений. + + Returns: + int: Количество записей в SpamLog + """ + async with self.session_maker() as session: + try: + query = select(func.count(SpamLog.id)) + result = await session.execute(query) + count = result.scalar_one() + return count + except Exception as e: + logger.error( + f"Ошибка подсчёта спам-логов: {e}", + log_type="DATABASE" + ) + return 0 + + async def reset_spam_stats(self) -> bool: + """ + Очищает всю статистику спама. + + Returns: + bool: True если успешно + """ + async with self.session_maker() as session: + try: + # Удаляем все записи + await session.execute(delete(SpamLog)) + await session.commit() + + logger.info("Статистика спама сброшена", log_type="DATABASE") + return True + + except Exception as e: + logger.error( + f"Ошибка сброса статистики: {e}", + log_type="DATABASE" + ) + await session.rollback() + return False + + +# Глобальный экземпляр менеджера +_manager_instance: Optional[BanWordsManager] = None + + +def get_manager() -> BanWordsManager: + """ + Возвращает глобальный экземпляр BanWordsManager (Singleton). + + Returns: + BanWordsManager: Менеджер банвордов + """ + global _manager_instance + if _manager_instance is None: + _manager_instance = BanWordsManager() + return _manager_instance diff --git a/database/migrate.py b/database/migrate.py new file mode 100644 index 0000000..6ac8ee2 --- /dev/null +++ b/database/migrate.py @@ -0,0 +1,51 @@ +# Создайте файл database/migrate.py + +""" +Миграция: добавление полей matched_word и match_type в SpamLog +""" +import asyncio +from sqlalchemy import text +from .manager import get_manager + + +async def migrate(): + """Добавляет поля matched_word и match_type если их нет""" + manager = get_manager() + await manager.init() + + async with manager.session_maker() as session: + try: + # Проверяем наличие колонок + result = await session.execute( + text("PRAGMA table_info(spam_logs)") + ) + columns = [row[1] for row in result.fetchall()] + + if 'matched_word' not in columns: + print("Добавляем колонку matched_word...") + await session.execute( + text("ALTER TABLE spam_logs ADD COLUMN matched_word VARCHAR(255)") + ) + await session.commit() + print("✅ Колонка matched_word добавлена") + + if 'match_type' not in columns: + print("Добавляем колонку match_type...") + await session.execute( + text("ALTER TABLE spam_logs ADD COLUMN match_type VARCHAR(50)") + ) + await session.commit() + print("✅ Колонка match_type добавлена") + + print("✅ Миграция завершена успешно!") + + except Exception as e: + print(f"❌ Ошибка миграции: {e}") + await session.rollback() + + finally: + await manager.close() + + +if __name__ == "__main__": + asyncio.run(migrate()) diff --git a/database/models.py b/database/models.py new file mode 100644 index 0000000..f0840e5 --- /dev/null +++ b/database/models.py @@ -0,0 +1,254 @@ +""" +SQLAlchemy модели для банвордов. +""" +from datetime import datetime, timezone +from enum import Enum as PyEnum +from typing import Optional + +from sqlalchemy import String, Integer, DateTime, Text, Enum, BigInteger +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column + +__all__ = ( + "Base", + "BanWordType", + "SpamMode", + "BanWord", + "TempBanWord", + "WhitelistWord", + "Admin", + "Setting", + "SpamStat", + "SpamLog", +) + + +class Base(DeclarativeBase): + """Базовый класс для всех моделей""" + pass + + +class BanWordType(str, PyEnum): + """Типы банвордов""" + SUBSTRING = "substring" + LEMMA = "lemma" + PART = "part" + CONFLICT_SUBSTRING = "conflict_substring" + CONFLICT_LEMMA = "conflict_lemma" + + +class SpamMode(str, PyEnum): + """Режимы работы спам-фильтра""" + NORMAL = "normal" + SILENCE = "silence" + CONFLICT = "conflict" + + +class BanWord(Base): + """ + Постоянные банворды. + + Attributes: + id: Уникальный ID + word: Само слово (lowercase) + type: Тип банворда + added_by: Telegram ID добавившего админа + added_at: Дата добавления + reason: Причина добавления + """ + __tablename__ = "banwords" + + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) + word: Mapped[str] = mapped_column(String(255), nullable=False, index=True) + type: Mapped[BanWordType] = mapped_column( + Enum(BanWordType, native_enum=False), + nullable=False, + index=True + ) + added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) + added_at: Mapped[datetime] = mapped_column( + DateTime, + default=datetime.now, + nullable=False + ) + reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + + def __repr__(self) -> str: + return f"" + + +class TempBanWord(Base): + """ + Временные банворды (с автоудалением). + + Attributes: + id: Уникальный ID + word: Само слово + type: Тип банворда + added_by: ID админа + added_at: Дата добавления + expires_at: Дата истечения + """ + __tablename__ = "temp_banwords" + + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) + word: Mapped[str] = mapped_column(String(255), nullable=False, index=True) + type: Mapped[BanWordType] = mapped_column( + Enum(BanWordType, native_enum=False), + nullable=False + ) + added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) + added_at: Mapped[datetime] = mapped_column( + DateTime, + default=datetime.now, + nullable=False + ) + expires_at: Mapped[datetime] = mapped_column( + DateTime, + nullable=False, + index=True + ) + + def is_expired(self) -> bool: + """Проверяет, истёк ли срок""" + return datetime.now() >= self.expires_at + + def __repr__(self) -> str: + return f"" + + +class WhitelistWord(Base): + """ + Белый список (исключения из проверки). + + Attributes: + id: Уникальный ID + word: Слово-исключение + added_by: ID админа + added_at: Дата добавления + reason: Причина (например, "ложное срабатывание") + """ + __tablename__ = "whitelist" + + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) + word: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True) + added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) + added_at: Mapped[datetime] = mapped_column( + DateTime, + default=datetime.now, + nullable=False + ) + reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + + def __repr__(self) -> str: + return f"" + + +class Admin(Base): + """ + Дополнительные администраторы бота. + + Attributes: + id: Уникальный ID записи + user_id: Telegram ID пользователя (уникальный) + added_by: ID суперадмина, который добавил + added_at: Дата добавления + permissions: JSON со списком прав (для будущего) + """ + __tablename__ = "admins" + + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) + user_id: Mapped[int] = mapped_column(Integer, nullable=False, unique=True, index=True) + added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) + added_at: Mapped[datetime] = mapped_column( + DateTime, + default=datetime.now, + nullable=False + ) + permissions: Mapped[Optional[str]] = mapped_column( + Text, + default="[]", + nullable=True + ) + + def __repr__(self) -> str: + return f"" + + +class Setting(Base): + """ + Настройки и состояния бота. + + Attributes: + key: Ключ настройки (primary key) + value: Значение (JSON string) + updated_at: Дата обновления + + Examples: + - silence_until: datetime ISO string + - conflict_until: datetime ISO string + - spam_mode: "normal"/"silence"/"conflict" + """ + __tablename__ = "settings" + + key: Mapped[str] = mapped_column(String(100), primary_key=True) + value: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + updated_at: Mapped[datetime] = mapped_column( + DateTime, + default=datetime.now, + onupdate=datetime.now, + nullable=False + ) + + def __repr__(self) -> str: + return f"" + + +class SpamStat(Base): + """ + Статистика удалённых спам-сообщений. + + Attributes: + id: Уникальный ID + user_id: Telegram ID отправителя + username: Username отправителя + chat_id: ID чата + message_text: Текст сообщения (до 500 символов) + matched_word: Слово, по которому сработал фильтр + match_type: Тип проверки (substring/lemma/part) + deleted_at: Дата удаления + """ + __tablename__ = "spam_stats" + + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) + user_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True) + username: Mapped[Optional[str]] = mapped_column(String(100), nullable=True) + chat_id: Mapped[int] = mapped_column(Integer, nullable=False) + message_text: Mapped[str] = mapped_column(Text, nullable=False) + matched_word: Mapped[str] = mapped_column(String(255), nullable=False) + match_type: Mapped[str] = mapped_column(String(50), nullable=False) + deleted_at: Mapped[datetime] = mapped_column( + DateTime, + default=datetime.now, + nullable=False, + index=True + ) + + def __repr__(self) -> str: + return f"" + + +class SpamLog(Base): + """Модель для логирования срабатываний спам-фильтра""" + __tablename__ = "spam_logs" + + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + user_id: Mapped[int] = mapped_column(BigInteger, nullable=False) + username: Mapped[str] = mapped_column(String(255), nullable=True) + chat_id: Mapped[int] = mapped_column(BigInteger, nullable=False) + message_text: Mapped[str] = mapped_column(Text, nullable=True) + matched_word: Mapped[str] = mapped_column(String(255), nullable=True) # <-- Должно быть! + match_type: Mapped[str] = mapped_column(String(50), nullable=True) # <-- Должно быть! + timestamp: Mapped[datetime] = mapped_column( + DateTime, + default=lambda: datetime.now(timezone.utc) + ) diff --git a/database/repository.py b/database/repository.py new file mode 100644 index 0000000..70d084b --- /dev/null +++ b/database/repository.py @@ -0,0 +1,798 @@ +""" +Repository для работы с банвордами через SQLAlchemy ORM. +""" +from typing import Set, List, Optional +from datetime import datetime, timedelta + +from sqlalchemy import select, delete, func, and_ + +from middleware.loggers import logger +from .database import Database +from .models import ( + BanWord, + TempBanWord, + WhitelistWord, + Admin, + Setting, + SpamStat, + BanWordType +) + +__all__ = ("BanWordsRepository",) + + +class BanWordsRepository: + """ + Repository для CRUD операций с банвордами. + + Все методы работают через SQLAlchemy ORM. + """ + + def __init__(self, db: Database): + """ + Args: + db: Экземпляр Database + """ + self.db = db + + # === BANWORDS === + + async def add_banword( + self, + word: str, + word_type: BanWordType, + added_by: Optional[int] = None, + reason: Optional[str] = None + ) -> bool: + """ + Добавляет постоянный банворд. + + Args: + word: Слово для блокировки + word_type: Тип банворда + added_by: ID админа, который добавил + reason: Причина добавления + + Returns: + bool: True если добавлен, False если уже существует + """ + try: + async with self.db.get_session() as session: + # Проверяем, существует ли уже + existing = await session.execute( + select(BanWord).where( + and_( + BanWord.word == word.lower(), + BanWord.type == word_type + ) + ) + ) + if existing.scalar_one_or_none(): + return False + + # Добавляем новый + banword = BanWord( + word=word.lower(), + type=word_type, + added_by=added_by, + reason=reason + ) + session.add(banword) + await session.commit() + + logger.info( + f"Добавлен банворд: '{word}' ({word_type.value})", + log_type="DATABASE" + ) + return True + + except Exception as e: + logger.error( + f"Ошибка добавления банворда: {e}", + log_type="DATABASE" + ) + return False + + async def remove_banword(self, word: str, word_type: BanWordType) -> bool: + """ + Удаляет банворд. + + Args: + word: Слово + word_type: Тип + + Returns: + bool: True если удалён + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + delete(BanWord).where( + and_( + BanWord.word == word.lower(), + BanWord.type == word_type + ) + ) + ) + await session.commit() + deleted = result.rowcount > 0 + + if deleted: + logger.info( + f"Удалён банворд: '{word}' ({word_type.value})", + log_type="DATABASE" + ) + return deleted + + except Exception as e: + logger.error( + f"Ошибка удаления банворда: {e}", + log_type="DATABASE" + ) + return False + + async def get_banwords(self, word_type: BanWordType) -> Set[str]: + """ + Получает все банворды определённого типа. + + Args: + word_type: Тип банвордов + + Returns: + Set[str]: Набор слов + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + select(BanWord.word).where(BanWord.type == word_type) + ) + return set(result.scalars().all()) + + except Exception as e: + logger.error( + f"Ошибка получения банвордов: {e}", + log_type="DATABASE" + ) + return set() + + async def get_all_banwords(self) -> dict[BanWordType, Set[str]]: + """ + Получает все банворды, сгруппированные по типам. + + Returns: + dict: {BanWordType: Set[str]} + """ + result = { + BanWordType.SUBSTRING: set(), + BanWordType.LEMMA: set(), + BanWordType.PART: set(), + BanWordType.CONFLICT_SUBSTRING: set(), + BanWordType.CONFLICT_LEMMA: set(), + } + + try: + async with self.db.get_session() as session: + banwords = await session.execute(select(BanWord)) + for banword in banwords.scalars(): + result[banword.type].add(banword.word) + + except Exception as e: + logger.error( + f"Ошибка получения всех банвордов: {e}", + log_type="DATABASE" + ) + + return result + + async def search_banwords(self, query: str, limit: int = 50) -> List[BanWord]: + """ + Поиск банвордов по частичному совпадению. + + Args: + query: Поисковый запрос + limit: Максимум результатов + + Returns: + List[BanWord]: Найденные банворды + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + select(BanWord) + .where(BanWord.word.contains(query.lower())) + .limit(limit) + ) + return list(result.scalars().all()) + + except Exception as e: + logger.error( + f"Ошибка поиска банвордов: {e}", + log_type="DATABASE" + ) + return [] + + # === TEMPORARY BANWORDS === + + async def add_temp_banword( + self, + word: str, + word_type: BanWordType, + minutes: int, + added_by: Optional[int] = None + ) -> bool: + """ + Добавляет временный банворд. + + Args: + word: Слово + word_type: Тип + minutes: Длительность в минутах + added_by: ID админа + + Returns: + bool: True если добавлен + """ + try: + async with self.db.get_session() as session: + # Проверяем существование + existing = await session.execute( + select(TempBanWord).where( + and_( + TempBanWord.word == word.lower(), + TempBanWord.type == word_type + ) + ) + ) + if existing.scalar_one_or_none(): + return False + + # Добавляем + expires_at = datetime.now() + timedelta(minutes=minutes) + temp_banword = TempBanWord( + word=word.lower(), + type=word_type, + added_by=added_by, + expires_at=expires_at + ) + session.add(temp_banword) + await session.commit() + + logger.info( + f"Добавлен временный банворд: '{word}' на {minutes} мин", + log_type="DATABASE" + ) + return True + + except Exception as e: + logger.error( + f"Ошибка добавления временного банворда: {e}", + log_type="DATABASE" + ) + return False + + async def remove_temp_banword(self, word: str, word_type: BanWordType) -> bool: + """Удаляет временный банворд досрочно""" + try: + async with self.db.get_session() as session: + result = await session.execute( + delete(TempBanWord).where( + and_( + TempBanWord.word == word.lower(), + TempBanWord.type == word_type + ) + ) + ) + await session.commit() + deleted = result.rowcount > 0 + + if deleted: + logger.info( + f"Удалён временный банворд: '{word}'", + log_type="DATABASE" + ) + return deleted + + except Exception as e: + logger.error( + f"Ошибка удаления временного банворда: {e}", + log_type="DATABASE" + ) + return False + + async def get_temp_banwords(self, word_type: BanWordType) -> Set[str]: + """ + Получает активные (не истёкшие) временные банворды. + + Args: + word_type: Тип банвордов + + Returns: + Set[str]: Набор активных временных слов + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + select(TempBanWord.word).where( + and_( + TempBanWord.type == word_type, + TempBanWord.expires_at > datetime.now() + ) + ) + ) + return set(result.scalars().all()) + + except Exception as e: + logger.error( + f"Ошибка получения временных банвордов: {e}", + log_type="DATABASE" + ) + return set() + + async def get_all_temp_banwords(self) -> dict[BanWordType, Set[str]]: + """Получает все активные временные банворды по типам""" + result = { + BanWordType.SUBSTRING: set(), + BanWordType.LEMMA: set(), + } + + try: + async with self.db.get_session() as session: + temp_banwords = await session.execute( + select(TempBanWord).where( + TempBanWord.expires_at > datetime.now() + ) + ) + for temp_banword in temp_banwords.scalars(): + if temp_banword.type in result: + result[temp_banword.type].add(temp_banword.word) + + except Exception as e: + logger.error( + f"Ошибка получения всех временных банвордов: {e}", + log_type="DATABASE" + ) + + return result + + async def cleanup_expired_temp_banwords(self) -> int: + """ + Удаляет истёкшие временные банворды. + + Returns: + int: Количество удалённых записей + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + delete(TempBanWord).where( + TempBanWord.expires_at <= datetime.now() + ) + ) + await session.commit() + deleted = result.rowcount + + if deleted > 0: + logger.info( + f"Удалено {deleted} истёкших временных банвордов", + log_type="DATABASE" + ) + return deleted + + except Exception as e: + logger.error( + f"Ошибка очистки временных банвордов: {e}", + log_type="DATABASE" + ) + return 0 + + # === WHITELIST === + + async def add_whitelist( + self, + word: str, + added_by: Optional[int] = None, + reason: Optional[str] = None + ) -> bool: + """Добавляет слово в белый список (исключение)""" + try: + async with self.db.get_session() as session: + # Проверяем существование + existing = await session.execute( + select(WhitelistWord).where( + WhitelistWord.word == word.lower() + ) + ) + if existing.scalar_one_or_none(): + return False + + # Добавляем + whitelist_word = WhitelistWord( + word=word.lower(), + added_by=added_by, + reason=reason + ) + session.add(whitelist_word) + await session.commit() + + logger.info( + f"Добавлено исключение: '{word}'", + log_type="DATABASE" + ) + return True + + except Exception as e: + logger.error( + f"Ошибка добавления исключения: {e}", + log_type="DATABASE" + ) + return False + + async def remove_whitelist(self, word: str) -> bool: + """Удаляет слово из белого списка""" + try: + async with self.db.get_session() as session: + result = await session.execute( + delete(WhitelistWord).where( + WhitelistWord.word == word.lower() + ) + ) + await session.commit() + deleted = result.rowcount > 0 + + if deleted: + logger.info( + f"Удалено исключение: '{word}'", + log_type="DATABASE" + ) + return deleted + + except Exception as e: + logger.error( + f"Ошибка удаления исключения: {e}", + log_type="DATABASE" + ) + return False + + async def get_whitelist(self) -> Set[str]: + """Получает все слова из белого списка""" + try: + async with self.db.get_session() as session: + result = await session.execute(select(WhitelistWord.word)) + return set(result.scalars().all()) + + except Exception as e: + logger.error( + f"Ошибка получения whitelist: {e}", + log_type="DATABASE" + ) + return set() + + # === ADMINS === + + async def add_admin( + self, + user_id: int, + added_by: Optional[int] = None + ) -> bool: + """Добавляет администратора""" + try: + async with self.db.get_session() as session: + # Проверяем существование + existing = await session.execute( + select(Admin).where(Admin.user_id == user_id) + ) + if existing.scalar_one_or_none(): + return False + + # Добавляем + admin = Admin(user_id=user_id, added_by=added_by) + session.add(admin) + await session.commit() + + logger.info( + f"Добавлен админ: {user_id}", + log_type="DATABASE" + ) + return True + + except Exception as e: + logger.error( + f"Ошибка добавления админа: {e}", + log_type="DATABASE" + ) + return False + + async def remove_admin(self, user_id: int) -> bool: + """Удаляет администратора""" + try: + async with self.db.get_session() as session: + result = await session.execute( + delete(Admin).where(Admin.user_id == user_id) + ) + await session.commit() + deleted = result.rowcount > 0 + + if deleted: + logger.info( + f"Удалён админ: {user_id}", + log_type="DATABASE" + ) + return deleted + + except Exception as e: + logger.error( + f"Ошибка удаления админа: {e}", + log_type="DATABASE" + ) + return False + + async def get_admins(self) -> Set[int]: + """Получает всех администраторов""" + try: + async with self.db.get_session() as session: + result = await session.execute(select(Admin.user_id)) + return set(result.scalars().all()) + + except Exception as e: + logger.error( + f"Ошибка получения админов: {e}", + log_type="DATABASE" + ) + return set() + + async def is_admin(self, user_id: int) -> bool: + """Проверяет, является ли пользователь админом""" + try: + async with self.db.get_session() as session: + result = await session.execute( + select(Admin).where(Admin.user_id == user_id) + ) + return result.scalar_one_or_none() is not None + + except Exception as e: + logger.error( + f"Ошибка проверки админа: {e}", + log_type="DATABASE" + ) + return False + + # === SETTINGS === + + async def set_setting(self, key: str, value: str) -> None: + """ + Сохраняет настройку (или обновляет существующую). + + Args: + key: Ключ настройки + value: Значение (строка или JSON) + """ + try: + async with self.db.get_session() as session: + # Проверяем существование + existing = await session.execute( + select(Setting).where(Setting.key == key) + ) + setting = existing.scalar_one_or_none() + + if setting: + # Обновляем существующую + setting.value = value + setting.updated_at = datetime.now() + else: + # Создаём новую + setting = Setting(key=key, value=value) + session.add(setting) + + await session.commit() + + except Exception as e: + logger.error( + f"Ошибка сохранения настройки: {e}", + log_type="DATABASE" + ) + + async def get_setting( + self, + key: str, + default: Optional[str] = None + ) -> Optional[str]: + """ + Получает значение настройки. + + Args: + key: Ключ настройки + default: Значение по умолчанию + + Returns: + Optional[str]: Значение или default + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + select(Setting.value).where(Setting.key == key) + ) + value = result.scalar_one_or_none() + return value if value is not None else default + + except Exception as e: + logger.error( + f"Ошибка получения настройки: {e}", + log_type="DATABASE" + ) + return default + + async def delete_setting(self, key: str) -> bool: + """Удаляет настройку""" + try: + async with self.db.get_session() as session: + result = await session.execute( + delete(Setting).where(Setting.key == key) + ) + await session.commit() + return result.rowcount > 0 + + except Exception as e: + logger.error( + f"Ошибка удаления настройки: {e}", + log_type="DATABASE" + ) + return False + + # === STATISTICS === + + async def log_spam_deletion( + self, + user_id: int, + username: str, + chat_id: int, + message_text: str, + matched_word: str, + match_type: str + ) -> None: + """ + Записывает статистику удалённого спам-сообщения. + + Args: + user_id: Telegram ID отправителя + username: Username отправителя + chat_id: ID чата + message_text: Текст сообщения (обрезается до 500 символов) + matched_word: Слово, по которому сработал фильтр + match_type: Тип проверки (substring/lemma/part/silence/conflict) + """ + try: + async with self.db.get_session() as session: + spam_stat = SpamStat( + user_id=user_id, + username=username, + chat_id=chat_id, + message_text=message_text[:500], + matched_word=matched_word, + match_type=match_type + ) + session.add(spam_stat) + await session.commit() + + except Exception as e: + logger.error( + f"Ошибка логирования статистики: {e}", + log_type="DATABASE" + ) + + async def get_spam_stats( + self, + limit: int = 100, + user_id: Optional[int] = None + ) -> List[SpamStat]: + """ + Получает последнюю статистику удалений. + + Args: + limit: Максимум записей + user_id: Фильтр по пользователю (опционально) + + Returns: + List[SpamStat]: Список записей статистики + """ + try: + async with self.db.get_session() as session: + query = select(SpamStat).order_by(SpamStat.deleted_at.desc()) + + if user_id: + query = query.where(SpamStat.user_id == user_id) + + query = query.limit(limit) + result = await session.execute(query) + return list(result.scalars().all()) + + except Exception as e: + logger.error( + f"Ошибка получения статистики: {e}", + log_type="DATABASE" + ) + return [] + + async def get_user_spam_count(self, user_id: int) -> int: + """Получает количество удалённых сообщений пользователя""" + try: + async with self.db.get_session() as session: + result = await session.execute( + select(func.count(SpamStat.id)).where( + SpamStat.user_id == user_id + ) + ) + return result.scalar_one() + + except Exception as e: + logger.error( + f"Ошибка подсчёта спама: {e}", + log_type="DATABASE" + ) + return 0 + + async def get_top_spammers(self, limit: int = 10) -> List[tuple[int, int]]: + """ + Получает топ спамеров. + + Args: + limit: Количество записей + + Returns: + List[tuple[int, int]]: [(user_id, count), ...] + """ + try: + async with self.db.get_session() as session: + result = await session.execute( + select( + SpamStat.user_id, + func.count(SpamStat.id).label('count') + ) + .group_by(SpamStat.user_id) + .order_by(func.count(SpamStat.id).desc()) + .limit(limit) + ) + return [(row.user_id, row.count) for row in result] + + except Exception as e: + logger.error( + f"Ошибка получения топ спамеров: {e}", + log_type="DATABASE" + ) + return [] + + # === GENERAL === + + async def get_stats(self) -> dict: + """Получает общую статистику БД""" + try: + async with self.db.get_session() as session: + banwords_count = await session.execute( + select(func.count(BanWord.id)) + ) + temp_banwords_count = await session.execute( + select(func.count(TempBanWord.id)) + ) + whitelist_count = await session.execute( + select(func.count(WhitelistWord.id)) + ) + admins_count = await session.execute( + select(func.count(Admin.id)) + ) + spam_stats_count = await session.execute( + select(func.count(SpamStat.id)) + ) + + return { + 'banwords': banwords_count.scalar_one(), + 'temp_banwords': temp_banwords_count.scalar_one(), + 'whitelist': whitelist_count.scalar_one(), + 'admins': admins_count.scalar_one(), + 'spam_deletions': spam_stats_count.scalar_one(), + } + + except Exception as e: + logger.error( + f"Ошибка получения статистики: {e}", + log_type="DATABASE" + ) + return {} diff --git a/locales/en/LC_MESSAGES/bot.mo b/locales/en/LC_MESSAGES/bot.mo new file mode 100644 index 0000000000000000000000000000000000000000..fc24c7e0dace18718e5e00784f58fc9be523e095 GIT binary patch literal 456 zcmYjNO;5r=5XHn(kDfh@i3bf%-7O+m!0=TJNvj0V`vOBLDZ9;fYvhM`@yGdF+^P{L zdC9z)mwA)-d2;+-v2|o|YH?nYe|2U154*&2HqmNJOM~MTzL3rnC4J~C1G6F{4ZmAp zE_bGsDQz&y<79>XBF=HHeAudu?5-3c?L?BgOSN+*Pjeh-62>0Gp)llw$GjV49JvSl z*5|y+>Wo<-PU$r%O%J*{vL, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: Bot Super Project 0.1\n" +"Report-Msgid-Bugs-To: john@doe-email.com\n" +"POT-Creation-Date: 2024-01-12 16:11+0500\n" +"PO-Revision-Date: 2025-08-10 19:33+0700\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: bot/handlers/commands/lang.py:43 +msgid "Выберите язык:" +msgstr "" + +#: bot/handlers/commands/lang.py:50 +#, python-brace-format +msgid "Язык {lang} не поддерживается!" +msgstr "" + +#: bot/handlers/commands/start.py:29 +msgid "Создать пост📔" +msgstr "" + +#: bot/handlers/commands/start.py:30 +msgid "Посмотреть список📋" +msgstr "" + +#: bot/handlers/commands/start.py:31 +msgid "Изменить язык🌐" +msgstr "" + +#: bot/handlers/commands/start.py:35 +#, python-brace-format +msgid "" +"Добро пожаловать, {name}!\n" +"\n" +"Мое имя - {bot_name}! Я искусственный интеллект и сказитель ваших " +"историй! \n" +"Моя цель — помочь вам сориентироваться и сделать ваши истории куда " +"интереснее! \n" +"Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на " +"клавиатуре!\n" +"\n" +"Интересный факт:\n" +"
{fact}
\n" +msgstr "" + diff --git a/locales/messages.pot b/locales/messages.pot new file mode 100644 index 0000000..1bfd65d --- /dev/null +++ b/locales/messages.pot @@ -0,0 +1,56 @@ +# Translations template for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Bot Super Project 0.1\n" +"Report-Msgid-Bugs-To: john@doe-email.com\n" +"POT-Creation-Date: 2024-01-12 16:11+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.13.1\n" + +#: bot/handlers/commands/lang.py:43 +msgid "Выберите язык:" +msgstr "" + +#: bot/handlers/commands/lang.py:50 +#, python-brace-format +msgid "Язык {lang} не поддерживается!" +msgstr "" + +#: bot/handlers/commands/start.py:29 +msgid "Создать пост📔" +msgstr "" + +#: bot/handlers/commands/start.py:30 +msgid "Посмотреть список📋" +msgstr "" + +#: bot/handlers/commands/start.py:31 +msgid "Изменить язык🌐" +msgstr "" + +#: bot/handlers/commands/start.py:35 +#, python-brace-format +msgid "" +"Добро пожаловать, {name}!\n" +"\n" +"Мое имя - {bot_name}! Я искусственный интеллект и сказитель ваших " +"историй! \n" +"Моя цель — помочь вам сориентироваться и сделать ваши истории куда " +"интереснее! \n" +"Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на " +"клавиатуре!\n" +"\n" +"Интересный факт:\n" +"
{fact}
\n" +msgstr "" + diff --git a/locales/ru/LC_MESSAGES/bot.mo b/locales/ru/LC_MESSAGES/bot.mo new file mode 100644 index 0000000000000000000000000000000000000000..bc4eb5548217ebaf42b4e822e64e66f5b6f099fe GIT binary patch literal 530 zcmYjOQBT`I3}(`v^2qZZj5Mkt=IkzQN0&CGg@&n80#)1X{b)@HO7Eh}1%brh*x%!c zA2Nq-6ib%;+242e+0XkQ|Ln1SVE@GaxdHF&E5|Qf#3nbh=8jelr)&I8w#tnT;mkN# z)FoN?R|VlqZ%(DL4$~^j*LYTE6)sH(cji`))`pNaDlhz%*?6<7C7xSSjvvE`auh-! zf({CaG64BKl=4_~g2LU9mD38x@{>5PX_@V_*OI!*Yh5Cfk6>1iurjyPhCWKD3? z_tI$^?-nh6;hh`pNb~<5OP<=%gZow%D%X8j-6~s=i)wd+y&bRF!wp%C^~$VsorTc5 a&Yky@G+ACY-{z4|sIIAiz?Uc7V(%{)Gm}pM literal 0 HcmV?d00001 diff --git a/locales/ru/LC_MESSAGES/bot.po b/locales/ru/LC_MESSAGES/bot.po new file mode 100644 index 0000000..82e0714 --- /dev/null +++ b/locales/ru/LC_MESSAGES/bot.po @@ -0,0 +1,59 @@ +# Russian translations for Bot Super Project. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the Bot Super Project +# project. +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: Bot Super Project 0.1\n" +"Report-Msgid-Bugs-To: john@doe-email.com\n" +"POT-Creation-Date: 2024-01-12 16:11+0500\n" +"PO-Revision-Date: 2025-08-10 19:33+0700\n" +"Last-Translator: FULL NAME \n" +"Language: ru\n" +"Language-Team: ru \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: bot/handlers/commands/lang.py:43 +msgid "Выберите язык:" +msgstr "" + +#: bot/handlers/commands/lang.py:50 +#, python-brace-format +msgid "Язык {lang} не поддерживается!" +msgstr "" + +#: bot/handlers/commands/start.py:29 +msgid "Создать пост📔" +msgstr "" + +#: bot/handlers/commands/start.py:30 +msgid "Посмотреть список📋" +msgstr "" + +#: bot/handlers/commands/start.py:31 +msgid "Изменить язык🌐" +msgstr "" + +#: bot/handlers/commands/start.py:35 +#, python-brace-format +msgid "" +"Добро пожаловать, {name}!\n" +"\n" +"Мое имя - {bot_name}! Я искусственный интеллект и сказитель ваших " +"историй! \n" +"Моя цель — помочь вам сориентироваться и сделать ваши истории куда " +"интереснее! \n" +"Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на " +"клавиатуре!\n" +"\n" +"Интересный факт:\n" +"
{fact}
\n" +msgstr "" + diff --git a/locales/uk/LC_MESSAGES/bot.mo b/locales/uk/LC_MESSAGES/bot.mo new file mode 100644 index 0000000000000000000000000000000000000000..914b389966f39d6f7e87cbf2417110ee037c1da8 GIT binary patch literal 530 zcmYjOO;6iE5Tz0)AA9a$Dp6DfV|E=VsS~I9a;ivn8zq7Jk_^V+>{{zJ0*SxD-{Zs& zVGM24kw%&~^WM(v%=5?HryaHr?4Q{88t|VTas0wXY;rSeZfNCjy2cB#Rc>?$L*rmk zmt^5j6@)LnIhDpbOsgzkX4Iyn*Uid4s@n*l5II^T1KZaxFD1<-+ zCnzM!0OYq&%0qD~1QT&icX`uv%R5EUMkzpk4_mE6amKtvRSuU{>8eo9*bpY?NdmtH zX$;*s9ZZw{U_743i$#yAI;&O2E$iEV0GFgTO$NG2(l2t~*sSNxirT6IC&q575Onzl ztEkn1_b~dZzeo{96886@3B~6~O85Z+n9jHt1%FH3=%fkX6r#)1KR&)om?I8YBUuw1 zbi8z$#@j_pUw9*<9cljGL&;M+x_8HAp>o}U)wQw}xu|wm*xvG*JzSB+Sg*`F*I5Yd b%iMWCNt5Me^KBmZgzAzC2z+_QEp}c33LTR{ literal 0 HcmV?d00001 diff --git a/locales/uk/LC_MESSAGES/bot.po b/locales/uk/LC_MESSAGES/bot.po new file mode 100644 index 0000000..39c6457 --- /dev/null +++ b/locales/uk/LC_MESSAGES/bot.po @@ -0,0 +1,59 @@ +# Ukrainian translations for Bot Super Project. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the Bot Super Project +# project. +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: Bot Super Project 0.1\n" +"Report-Msgid-Bugs-To: john@doe-email.com\n" +"POT-Creation-Date: 2024-01-12 16:11+0500\n" +"PO-Revision-Date: 2025-08-10 19:33+0700\n" +"Last-Translator: FULL NAME \n" +"Language: uk\n" +"Language-Team: uk \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: bot/handlers/commands/lang.py:43 +msgid "Выберите язык:" +msgstr "" + +#: bot/handlers/commands/lang.py:50 +#, python-brace-format +msgid "Язык {lang} не поддерживается!" +msgstr "" + +#: bot/handlers/commands/start.py:29 +msgid "Создать пост📔" +msgstr "" + +#: bot/handlers/commands/start.py:30 +msgid "Посмотреть список📋" +msgstr "" + +#: bot/handlers/commands/start.py:31 +msgid "Изменить язык🌐" +msgstr "" + +#: bot/handlers/commands/start.py:35 +#, python-brace-format +msgid "" +"Добро пожаловать, {name}!\n" +"\n" +"Мое имя - {bot_name}! Я искусственный интеллект и сказитель ваших " +"историй! \n" +"Моя цель — помочь вам сориентироваться и сделать ваши истории куда " +"интереснее! \n" +"Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на " +"клавиатуре!\n" +"\n" +"Интересный факт:\n" +"
{fact}
\n" +msgstr "" + diff --git a/main.py b/main.py new file mode 100644 index 0000000..f040a64 --- /dev/null +++ b/main.py @@ -0,0 +1,172 @@ +""" +Точка входа PrimoGuard Bot +""" +from asyncio import run + +from configs import settings +from bot import bot, dp, BotInfo, WebhookManager, setup_middlewares, router +from database import get_manager +from middleware.loggers import logger + +__all__ = ("main",) + + +async def setup_services(setup_webhook: bool = True) -> str: + """ + Инициализация всех сервисов: БД и бот. + + Args: + setup_webhook: Устанавливать ли webhook в BotInfo.setup() + + Returns: + str: Username бота + """ + # База данных + manager = get_manager() + await manager.init() + + stats = await manager.get_stats() + logger.info( + f"📊 БД инициализирована: {stats.get('total_banwords', 0)} банвордов", + log_type="DATABASE" + ) + + # Бот: получение информации (БЕЗ webhook) + await BotInfo.setup(bots=bot, setup_webhook=setup_webhook) + + # ВАЖНО: Регистрируем middleware и роутеры ДО установки webhook + setup_middlewares( + dp=dp, + bot=bot, + enable_spam_check=settings.ANTI_SPAM, + channel_ids=[], + ) + + # Подключение маршрутов + dp.include_router(router) + + logger.info("✓ Все handlers и middleware зарегистрированы", log_type="STARTUP") + + return BotInfo.username + + +async def on_startup(app) -> None: + """Выполняется при запуске webhook-сервера.""" + # 1. Инициализируем всё БЕЗ webhook + username = await setup_services(setup_webhook=False) + + # 2. ТЕПЕРЬ устанавливаем webhook (когда всё готово) + webhook = WebhookManager(bot, dp) + + if settings.WEBHOOK_URL: + success = await webhook.setup( + webhook_url=settings.WEBHOOK_URL, + secret_token=settings.SECRET_TOKEN, + drop_pending_updates=True + ) + + if success: + logger.success( + f"✅ Бот @{username} запущен в режиме Webhook", + log_type="STARTUP" + ) + else: + logger.error( + "❌ Не удалось установить webhook, но сервер запущен", + log_type="STARTUP" + ) + else: + logger.warning( + "⚠️ WEBHOOK_URL не указан", + log_type="STARTUP" + ) + + +async def on_shutdown(app) -> None: + """Очистка ресурсов при остановке сервера.""" + logger.info("👋 Остановка бота...", log_type="SHUTDOWN") + + try: + await get_manager().close() + await bot.session.close() + except Exception as e: + logger.error(f"Ошибка при закрытии: {e}", log_type="SHUTDOWN") + + logger.success("✅ Бот остановлен", log_type="SHUTDOWN") + + +def start_webhook() -> None: + """Запуск в режиме Webhook (синхронный).""" + logger.setup() + + webhook = WebhookManager(bot, dp) + + # ВАЖНО: Конфигурируем webhook ПЕРЕД on_startup + webhook.configure() + + # Добавляем startup/shutdown handlers + webhook.app.on_startup.append(on_startup) + webhook.app.on_shutdown.append(on_shutdown) + + # Запускаем webhook сервер + logger.info("🌐 Запуск Webhook сервера...", log_type="MAIN") + webhook.run() + + +async def start_polling() -> None: + """Запуск в режиме Polling (асинхронный).""" + logger.setup() + + try: + username = await setup_services(setup_webhook=False) + + # Удаляем webhook для polling режима + webhook = WebhookManager(bot, dp) + await webhook.delete(drop_pending_updates=True) + + logger.success( + f"✅ Бот @{username} запущен в режиме Polling", + log_type="STARTUP" + ) + + # Запускаем polling + await dp.start_polling(bot, drop_pending_updates=True) + + except Exception as e: + logger.critical( + f"🔥 Критическая ошибка: {e}", + log_type="MAIN" + ) + raise + + finally: + try: + await bot.session.close() + await get_manager().close() + except: + pass + + +def main() -> None: + """Входная точка проекта.""" + try: + if settings.WEBHOOK: + # ========== WEBHOOK РЕЖИМ ========== + start_webhook() + else: + # ========== POLLING РЕЖИМ ========== + run(start_polling()) + + except KeyboardInterrupt: + logger.info("⚠️ Остановка по сигналу Ctrl+C", log_type="MAIN") + + except Exception as e: + logger.critical( + f"🔥 Критическая ошибка при запуске: {e}", + log_type="MAIN" + ) + raise + + +if __name__ == "__main__": + main() diff --git a/middleware/__init__.py b/middleware/__init__.py new file mode 100644 index 0000000..e719cd0 --- /dev/null +++ b/middleware/__init__.py @@ -0,0 +1,2 @@ +from .loggers import * +from .validators import * diff --git a/middleware/loggers/__init__.py b/middleware/loggers/__init__.py new file mode 100644 index 0000000..d668488 --- /dev/null +++ b/middleware/loggers/__init__.py @@ -0,0 +1 @@ +from .logs import * diff --git a/middleware/loggers/logs.py b/middleware/loggers/logs.py new file mode 100644 index 0000000..f6a0479 --- /dev/null +++ b/middleware/loggers/logs.py @@ -0,0 +1,364 @@ +""" +Кастомный логгер с поддержкой декораторов и прямого вызова +""" +from sys import stderr +from pathlib import Path +from functools import wraps +from inspect import iscoroutinefunction +from typing import Any, Callable, Optional, TypeVar, Union, cast, Final +from contextlib import contextmanager + +from loguru import logger as nlogger +from aiogram.types import Message, User, CallbackQuery + +from configs import settings + +# Экспортируемые объекты +__all__ = ('Logger', 'setup_logging', 'logger', 'log') + +# Универсальный тип для функций +F = TypeVar('F', bound=Callable[..., Any]) + +# Типы для aiogram событий +EventType = Union[Message, CallbackQuery] + + +class Logger: + """ + Кастомный логгер с поддержкой декораторов, прямого вызова и контекстных менеджеров. + + Features: + - Декораторы для sync/async функций + - Прямой вызов методов (debug, info, warning, error, critical) + - Автоматическое извлечение юзера из Message/CallbackQuery + - Раздельные файлы логов по уровням + - Ротация и retention логов + - Контекстные менеджеры для блоков кода + """ + + # Формат логов + _log_format: Final[str] = ( + '{time:YYYY-MM-DD HH:mm:ss.SSS} | ' + '{extra[system]}-{extra[log_type]} | ' + '{extra[user]} | {message}' + ) + + + def __init__(self, system_name: str = 'PRIMO') -> None: + """ + Инициализация логгера. + + Args: + system_name: Имя системы для логирования (по умолчанию из settings) + """ + self.system_name = system_name or settings.PROJECT_NAME + self._setup_done = False + + def setup(self, start: bool = True) -> None: + """ + Настройка обработчиков Loguru: консоль и файлы. + + Args: + start: Если True, сразу логирует запуск проекта + """ + if self._setup_done: + return + + # Полная очистка настроек + nlogger.remove() + + # Создание директории для файловых логов + log_dir: Path = settings.LOG_DIR + if not log_dir.exists(): + log_dir.mkdir(parents=True, exist_ok=True) + + # Консольный лог + if settings.LOG_CONSOLE: + nlogger.add( + sink=stderr, + format=self._log_format, + colorize=True, + level='INFO', + filter=lambda rec: rec['extra'].get('log_type') != 'TRACE' + ) + + # Файловые логи + if settings.LOG_FILE: + # Общий лог со всеми уровнями + nlogger.add( + sink=log_dir / 'bot.log', + rotation=settings.LOG_ROTATION, + retention=settings.LOG_RETENTION, + format=self._log_format, + level='DEBUG', + enqueue=True, + backtrace=True, + diagnose=True, + encoding='utf-8' + ) + + # Раздельные логи по уровням + log_levels = { + 'INFO': 'info.log', + 'WARNING': 'warning.log', + 'ERROR': 'error.log', + 'CRITICAL': 'critical.log' + } + + + for level_name, filename in log_levels.items(): + nlogger.add( + sink=log_dir / filename, + rotation='10 MB', + retention=settings.LOG_RETENTION, + format=self._log_format, + level=level_name, + filter=lambda rec, lvl=level_name: rec['level'].name == lvl, + enqueue=True, + encoding='utf-8' + ) + + self._setup_done = True + + # Логируем старт + if start: + self.log_entry( + level='INFO', + text=f'Запуск проекта {self.system_name}...', + log_type='START' + ) + + + @staticmethod + def format_user(event: Optional[EventType] = None) -> str: + """ + Форматирует имя пользователя из объекта Message или CallbackQuery. + + Args: + event: Объект Message или CallbackQuery + + Returns: + str: Строка '@username' или 'id' или '@System' + """ + if event is None: + return '@System' + + # Извлекаем пользователя из Message или CallbackQuery + user: Optional[User] = None + if isinstance(event, Message): + user = event.from_user + elif isinstance(event, CallbackQuery): + user = event.from_user + + if user is None: + return '@System' + + return f"@{user.username}" if user.username else f"id{user.id}" + + def log_entry( + self, + level: str, + text: str, + log_type: str = 'SYSTEM', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """ + Основной метод для записи логов. + + Args: + level: Уровень логирования ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL') + text: Сообщение для логирования + log_type: Кастомный тип лога (например, 'HANDLER', 'COMMAND', 'SPAM') + user: Явно указанный пользователь (если None, извлекается из message) + message: Объект Message/CallbackQuery для извлечения юзера + """ + actual_user: str = user or self.format_user(message) + nlogger.bind( + system=self.system_name, + user=actual_user, + log_type=log_type + ).log(level, text) + + def log( + self, + level: str = 'INFO', + log_type: str = 'HANDLER', + text: Optional[str] = None + ) -> Callable[[F], F]: + """ + Декоратор для логирования функций (sync и async). + + Args: + level: Уровень логирования + log_type: Категория лога + text: Кастомный текст сообщения (если None, используется имя функции) + + Returns: + Декорированную функцию + + Example: + ```python + @logger.log(level='INFO', log_type='COMMAND', text='Команда /start') + async def start_handler(message: Message): + await message.answer("Привет!") + ``` + """ + + def decorator(func: F) -> F: + is_coroutine = iscoroutinefunction(func) + action_text = text or f'Вызов {func.__name__}' + + @wraps(func) + def sync_wrapper(*args: Any, **kwargs: Any) -> Any: + message = self._find_event(args) + self.log_entry(level, f"[▶] {action_text}", log_type, message=message) + try: + result = func(*args, **kwargs) + self.log_entry(level, f"[✓] {action_text}", log_type, message=message) + return result + except Exception as e: + self.log_entry( + 'ERROR', + f"[✗] {action_text} | Exception: {e!r}", + log_type, + message=message + ) + raise + + @wraps(func) + async def async_wrapper(*args: Any, **kwargs: Any) -> Any: + message = self._find_event(args) + self.log_entry(level, f"[▶] {action_text}", log_type, message=message) + try: + result = await func(*args, **kwargs) + self.log_entry(level, f"[✓] {action_text}", log_type, message=message) + return result + except Exception as e: + self.log_entry( + 'ERROR', + f"[✗] {action_text} | Exception: {e!r}", + log_type, + message=message + ) + raise + + return cast(F, async_wrapper if is_coroutine else sync_wrapper) + + return decorator + + @staticmethod + def _find_event(args: tuple[Any, ...]) -> Optional[EventType]: + """ + Ищет объект Message или CallbackQuery в аргументах функции. + + Args: + args: Аргументы функции + + Returns: + Найденный Message/CallbackQuery или None + """ + for arg in args: + if isinstance(arg, (Message, CallbackQuery)): + return arg + return None + + # ================= МЕТОДЫ ДЛЯ ПРЯМОГО ВЫЗОВА ================= + + def debug( + self, + text: str, + log_type: str = 'DEBUG', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """Логирование уровня DEBUG""" + self.log_entry('DEBUG', text, log_type, user, message) + + def info( + self, + text: str, + log_type: str = 'INFO', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """Логирование уровня INFO""" + self.log_entry('INFO', text, log_type, user, message) + + def warning( + self, + text: str, + log_type: str = 'WARNING', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """Логирование уровня WARNING""" + self.log_entry('WARNING', text, log_type, user, message) + + def error( + self, + text: str, + log_type: str = 'ERROR', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """Логирование уровня ERROR""" + self.log_entry('ERROR', text, log_type, user, message) + + def critical( + self, + text: str, + log_type: str = 'CRITICAL', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """Логирование уровня CRITICAL""" + self.log_entry('CRITICAL', text, log_type, user, message) + + def success( + self, + text: str, + log_type: str = 'SUCCESS', + user: Optional[str] = None, + message: Optional[EventType] = None + ) -> None: + """Логирование успешного выполнения (уровень INFO)""" + self.log_entry('INFO', f"✓ {text}", log_type, user, message) + + # ================= КОНТЕКСТНЫЕ МЕНЕДЖЕРЫ ================= + + @contextmanager + def log_context( + self, + action: str, + log_type: str = 'CONTEXT', + level: str = 'INFO', + message: Optional[EventType] = None + ): + """ + Контекстный менеджер для логирования блока кода. + + Example: + ```python + with logger.log_context("Обработка данных", log_type='DATA'): + # ... ваш код ... + pass + ``` + """ + self.log_entry(level, f"[▶] {action}", log_type, message=message) + try: + yield + self.log_entry(level, f"[✓] {action}", log_type, message=message) + except Exception as e: + self.log_entry('ERROR', f"[✗] {action} | Exception: {e!r}", log_type, message=message) + raise + + +# ================= ГЛОБАЛЬНЫЙ ЭКЗЕМПЛЯР ================= + +# Создаем глобальный экземпляр логгера +logger: Logger = Logger(system_name="PRIMO") + +# Алиасы для обратной совместимости +setup_logging = logger.setup +log = logger.log diff --git a/middleware/validators/__init__.py b/middleware/validators/__init__.py new file mode 100644 index 0000000..98878dc --- /dev/null +++ b/middleware/validators/__init__.py @@ -0,0 +1,2 @@ +from .email_vld import * +from .url_vld import * diff --git a/middleware/validators/email_vld.py b/middleware/validators/email_vld.py new file mode 100644 index 0000000..5288517 --- /dev/null +++ b/middleware/validators/email_vld.py @@ -0,0 +1,24 @@ +from typing import Optional + +from email_validator import validate_email, EmailNotValidError, ValidatedEmail + +# Настройка экспорта из этого модуля +__all__ = ("valid_email",) + + +def valid_email(email: str) -> Optional[str]: + """ + Валидация почты через библиотеку. + + :param email: Получаемая почта. + :return: Нормализированная почта. + """ + try: + # Провека почты на валидность + email: ValidatedEmail = validate_email(email) + + except EmailNotValidError: + return None + + # Возвращение строки с нормализированной почтой + return email.normalized diff --git a/middleware/validators/url_vld.py b/middleware/validators/url_vld.py new file mode 100644 index 0000000..6da66da --- /dev/null +++ b/middleware/validators/url_vld.py @@ -0,0 +1,42 @@ +from re import Pattern, compile + +# Настройка экспорта +__all__ = ("valid_url", "url_to_text",) + + +def valid_url(url: str) -> bool: + """ + Проверяет, является ли строка валидной ссылкой (URL). + + :param url: Строка для проверки. + :return: True, если строка является валидным URL, иначе False. + """ + url_pattern: Pattern[str] = compile( + r'^(https?://)?' # Протокол (http или https, необязателен) + r'([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}' # Домен + r'(:\d+)?' # Порт (необязателен) + r'(/[-a-zA-Z0-9@:%_+.~#?&/=]*)?$' # Путь, параметры и фрагменты + ) + return bool(url_pattern.match(url)) + + +def url_to_text(text: str, url: str) -> str: + """ + Преобразует текст в HTML ссылку с указанным URL. + + Эта функция генерирует HTML-ссылку с переданным текстом и URL, используя тег `<а>`, и делает ссылку жирной. + + :param text: Текст, который будет отображаться для ссылки. + :param url: URL, который будет привязан к тексту. + :return: Строка с HTML кодом для ссылки, если URL валиден. + :raises ValueError: Если URL невалиден. + """ + try: + if not valid_url(url): # Проверяем, является ли URL валидным + raise ValueError(f"Переданный URL '{url}' невалиден.") + + # Генерация HTML-ссылки + return f'{text}' + + except ValueError as e: + raise e # Перебрасываем ошибку выше для дальнейшей обработки или уведомления diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..4385194 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,43 @@ +[project] +name = "primoexamplebot" +version = "0.1.0" +description = "none" +authors = [ + {name = "admin",email = "inkscaper0349@outlook.com"} +] +license = {text = "MIT License"} +readme = "README.md" +requires-python = ">=3.10,<4.0" +dependencies = [ + "aiogram (>=3.22.0,<4.0.0)", + "loguru (>=0.7.3,<0.8.0)", + "uvicorn (>=0.35.0,<0.36.0)", + "fastapi (>=0.116.1,<0.117.0)", + "pydantic-settings (>=2.10.1,<3.0.0)", + "sqlalchemy (>=2.0.43,<3.0.0)", + "babel (>=2.17.0,<3.0.0)", + "aiosqlite (>=0.21.0,<0.22.0)", + "email-validator (>=2.3.0,<3.0.0)", + "apscheduler (>=3.11.0,<4.0.0)", + "pymorphy3 (>=2.0.6,<3.0.0)", +] + + +[build-system] +requires = ["poetry-core>=2.0.0,<3.0.0"] +build-backend = "poetry.core.masonry.api" + + +[tool.poetry] +package-mode = false + +[tool.poetry.group.dev.dependencies] +pytest = "^8.4.1" +pytest-asyncio = "^1.1.0" + +[tool.pytest.ini_options] +asyncio_mode = "auto" +testpaths = ["tests"] +python_files = "test_*.py" +python_classes = "Test*" +python_functions = "test_*"