Обновлен Python до версии 3.11.9 и изменены зависимости в Dockerfile и pyproject.toml. Удалены устаревшие файлы RATE_LIMITING_SOLUTION.md и тесты для rate limiting.
Обновлены пути к библиотекам в Dockerfile для соответствия новой версии Python. Исправлены все тесты, теперь все проходят
This commit is contained in:
215
.cursor/rules/handlers-patterns.md
Normal file
215
.cursor/rules/handlers-patterns.md
Normal file
@@ -0,0 +1,215 @@
|
||||
---
|
||||
description: "Паттерны для создания handlers, services и обработки событий aiogram"
|
||||
globs: ["helper_bot/handlers/**/*.py"]
|
||||
---
|
||||
|
||||
# Паттерны для Handlers
|
||||
|
||||
## Структура модуля handler
|
||||
|
||||
Каждый модуль handler (admin, callback, group, private, voice) должен содержать:
|
||||
|
||||
```
|
||||
handlers/{module}/
|
||||
├── __init__.py # Экспорт router
|
||||
├── {module}_handlers.py # Основные handlers
|
||||
├── services.py # Бизнес-логика
|
||||
├── exceptions.py # Кастомные исключения
|
||||
├── dependencies.py # Dependency injection (опционально)
|
||||
├── constants.py # Константы (FSM states, messages)
|
||||
└── utils.py # Вспомогательные функции (опционально)
|
||||
```
|
||||
|
||||
## Создание Router
|
||||
|
||||
```python
|
||||
from aiogram import Router
|
||||
|
||||
# Создаем роутер
|
||||
router = Router()
|
||||
|
||||
# Регистрируем middleware (если нужно)
|
||||
router.message.middleware(SomeMiddleware())
|
||||
|
||||
# Экспортируем в __init__.py
|
||||
# from .{module}_handlers import router
|
||||
```
|
||||
|
||||
## Структура Handler
|
||||
|
||||
```python
|
||||
from aiogram import Router, types
|
||||
from aiogram.filters import Command, StateFilter
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from helper_bot.filters.main import ChatTypeFilter
|
||||
from logs.custom_logger import logger
|
||||
from helper_bot.utils.metrics import track_time, track_errors
|
||||
|
||||
router = Router()
|
||||
|
||||
@router.message(
|
||||
ChatTypeFilter(chat_type=["private"]),
|
||||
Command('command_name')
|
||||
)
|
||||
@track_time("handler_name", "module_name")
|
||||
@track_errors("module_name", "handler_name")
|
||||
async def handler_function(
|
||||
message: types.Message,
|
||||
state: FSMContext,
|
||||
bot_db: AsyncBotDB, # Из DependenciesMiddleware
|
||||
settings: dict, # Из DependenciesMiddleware
|
||||
**kwargs
|
||||
):
|
||||
"""Описание handler."""
|
||||
try:
|
||||
# Логирование
|
||||
logger.info(f"Обработка команды от пользователя: {message.from_user.id}")
|
||||
|
||||
# Получение данных из state (если нужно)
|
||||
data = await state.get_data()
|
||||
|
||||
# Вызов сервиса для бизнес-логики
|
||||
service = SomeService(bot_db, settings)
|
||||
result = await service.do_something()
|
||||
|
||||
# Ответ пользователю
|
||||
await message.answer("Результат")
|
||||
|
||||
# Обновление state (если нужно)
|
||||
await state.set_state("NEW_STATE")
|
||||
|
||||
except SomeCustomException as e:
|
||||
# Обработка кастомных исключений
|
||||
await message.answer(f"Ошибка: {str(e)}")
|
||||
logger.error(f"Ошибка в handler: {e}")
|
||||
except Exception as e:
|
||||
# Обработка общих ошибок
|
||||
await handle_error(message, e, state)
|
||||
logger.error(f"Неожиданная ошибка: {e}")
|
||||
```
|
||||
|
||||
## Service Layer
|
||||
|
||||
Бизнес-логика выносится в сервисы:
|
||||
|
||||
```python
|
||||
from logs.custom_logger import logger
|
||||
from helper_bot.utils.metrics import track_time, track_errors
|
||||
|
||||
class SomeService:
|
||||
"""Сервис для работы с ..."""
|
||||
|
||||
def __init__(self, bot_db: AsyncBotDB, settings: dict):
|
||||
self.bot_db = bot_db
|
||||
self.settings = settings
|
||||
|
||||
@track_time("method_name", "service_name")
|
||||
@track_errors("service_name", "method_name")
|
||||
async def do_something(self) -> SomeResult:
|
||||
"""Описание метода."""
|
||||
try:
|
||||
# Работа с БД через bot_db
|
||||
data = await self.bot_db.some_method()
|
||||
|
||||
# Бизнес-логика
|
||||
result = self._process_data(data)
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка в сервисе: {e}")
|
||||
raise
|
||||
```
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
### Через DependenciesMiddleware (глобально)
|
||||
- `bot_db: AsyncBotDB` - доступен во всех handlers
|
||||
- `settings: dict` - настройки из .env
|
||||
- `bot: Bot` - экземпляр бота
|
||||
- `dp: Dispatcher` - dispatcher
|
||||
|
||||
### Через MagicData (локально)
|
||||
```python
|
||||
from aiogram.filters import MagicData
|
||||
from typing import Annotated
|
||||
from helper_bot.handlers.admin.dependencies import BotDB, Settings
|
||||
|
||||
@router.message(
|
||||
Command('admin'),
|
||||
MagicData(bot_db=BotDB, settings=Settings)
|
||||
)
|
||||
async def handler(
|
||||
message: types.Message,
|
||||
bot_db: Annotated[AsyncBotDB, BotDB],
|
||||
settings: Annotated[dict, Settings]
|
||||
):
|
||||
...
|
||||
```
|
||||
|
||||
### Через фабрики (для сервисов)
|
||||
```python
|
||||
# В dependencies.py
|
||||
def get_some_service() -> SomeService:
|
||||
"""Фабрика для SomeService"""
|
||||
bdf = get_global_instance()
|
||||
db = bdf.get_db()
|
||||
settings = bdf.settings
|
||||
return SomeService(db, settings)
|
||||
|
||||
# В handlers
|
||||
@router.message(Command('cmd'))
|
||||
async def handler(
|
||||
message: types.Message,
|
||||
service: Annotated[SomeService, get_some_service()]
|
||||
):
|
||||
...
|
||||
```
|
||||
|
||||
## FSM (Finite State Machine)
|
||||
|
||||
```python
|
||||
# Определение состояний в constants.py
|
||||
FSM_STATES = {
|
||||
"ADMIN": "ADMIN",
|
||||
"AWAIT_INPUT": "AWAIT_INPUT",
|
||||
...
|
||||
}
|
||||
|
||||
# Установка состояния
|
||||
await state.set_state(FSM_STATES["ADMIN"])
|
||||
|
||||
# Получение состояния
|
||||
current_state = await state.get_state()
|
||||
|
||||
# Сохранение данных
|
||||
await state.update_data(key=value)
|
||||
|
||||
# Получение данных
|
||||
data = await state.get_data()
|
||||
value = data.get("key")
|
||||
|
||||
# Очистка состояния
|
||||
await state.clear()
|
||||
```
|
||||
|
||||
## Фильтры
|
||||
|
||||
Используйте кастомные фильтры из `helper_bot.filters.main`:
|
||||
- `ChatTypeFilter` - фильтр по типу чата (private, group, supergroup)
|
||||
|
||||
## Декораторы для метрик
|
||||
|
||||
Всегда добавляйте декораторы метрик к handlers и методам сервисов:
|
||||
|
||||
```python
|
||||
@track_time("handler_name", "module_name") # Измерение времени выполнения
|
||||
@track_errors("module_name", "handler_name") # Отслеживание ошибок
|
||||
@db_query_time("method_name", "table_name", "operation") # Для БД операций
|
||||
```
|
||||
|
||||
## Обработка ошибок
|
||||
|
||||
- Используйте кастомные исключения из `exceptions.py`
|
||||
- Обрабатывайте исключения в handlers
|
||||
- Логируйте все ошибки через `logger.error()`
|
||||
- Используйте декоратор `@error_handler` для автоматической обработки (если есть)
|
||||
Reference in New Issue
Block a user