# 🤖 AnonBot - Telegram бот для анонимных вопросов
Telegram-бот для приема и обработки анонимных вопросов с использованием aiogram 3.x.
## ✨ Возможности
- 🔗 **Персональные ссылки** - каждый пользователь получает уникальную ссылку для приема вопросов
- 👤 **Анонимность** - вопросы отправляются анонимно, личность отправителя скрыта
- 💬 **Интерактивные ответы** - удобный интерфейс для ответов на вопросы через inline кнопки
- 🔢 **Локальная нумерация** - каждый пользователь видит свои вопросы с номерами #1, #2, #3... вместо глобальных ID
- 📊 **Статистика** - подробная статистика для администраторов
- 🗄️ **База данных** - SQLite для хранения пользователей и вопросов с автоматической нумерацией
- 👑 **Админ панель** - управление ботом для администраторов
- 🔍 **Суперпользователи** - расширенные права для модерации с отображением информации об авторах вопросов
- 🏗️ **Современная архитектура** - система инъекции зависимостей для лучшей тестируемости
- 📝 **Продвинутое логирование** - автоматические декораторы, контекстное логирование, FSM отслеживание
- 🛡️ **Безопасность** - валидация данных, обработка ошибок, система ролей
- 🔍 **Централизованная валидация** - автоматическая валидация всех входных данных с санитизацией
- 🔐 **Система разрешений** - гибкая система разрешений с соблюдением принципа OCP
- 📈 **Prometheus метрики** - полный мониторинг производительности и состояния бота
## 🚀 Быстрый старт
### 1. Установка зависимостей
```bash
pip install -r requirements.txt
pip install dependency-injector # Для системы инъекции зависимостей
```
### 2. Настройка конфигурации
Создайте файл `.env` в корневой директории проекта:
```env
# Токен бота от @BotFather
BOT_TOKEN=your_bot_token_here
# ID администраторов через запятую (можно получить у @userinfobot)
ADMINS=123456789,987654321
# Путь к базе данных SQLite
DATABASE_PATH=database/anon_qna.db
# Режим отладки (true/false)
DEBUG=false
# Максимальная длина вопроса
MAX_QUESTION_LENGTH=1000
# Максимальная длина ответа
MAX_ANSWER_LENGTH=2000
```
### 3. Запуск бота
#### Локальный запуск
```bash
python main.py
```
или
```bash
python bot.py
```
#### Запуск в Docker
1. Соберите Docker образ:
```bash
docker build -t anon-bot .
```
2. Запустите контейнер:
```bash
docker run -d \
--name anon-bot \
--restart unless-stopped \
-p 8081:8081 \
-v $(pwd)/database:/app/database \
-v $(pwd)/logs:/app/logs \
-e BOT_TOKEN=your_bot_token_here \
-e ADMINS=123456789,987654321 \
-e DEBUG=false \
anon-bot
```
3. Проверьте статус:
```bash
docker logs anon-bot
```
4. Проверьте метрики:
```bash
curl http://localhost:8081/health
```
## 📄 PID файл и мониторинг процесса
AnonBot автоматически создает PID файл для отслеживания процесса и предоставляет детальную информацию о состоянии через HTTP эндпоинты.
### PID файл
- **Расположение**: `/tmp/anon_bot.pid`
- **Содержимое**: PID процесса бота
- **Автоматическое управление**: создается при запуске, удаляется при остановке
- **Проверка дублирования**: предотвращает запуск нескольких экземпляров
### Эндпоинт /status
Предоставляет детальную информацию о процессе:
```bash
curl http://localhost:8081/status
```
**Пример ответа:**
```json
{
"status": "running",
"pid": 12345,
"uptime": "2ч 15м",
"memory_usage_mb": 45.2,
"cpu_percent": 0.1,
"timestamp": 1705312200.5
}
```
**Поля ответа:**
- `status` - статус процесса (running/stopped/not_found/error)
- `pid` - идентификатор процесса
- `uptime` - время работы в человекочитаемом формате
- `memory_usage_mb` - использование памяти в МБ
- `cpu_percent` - загрузка CPU в процентах
- `timestamp` - время ответа
### Тестирование
Для тестирования PID функционала можно использовать curl:
```bash
# Проверка статуса процесса
curl http://localhost:8081/status
# Проверка всех эндпоинтов
curl http://localhost:8081/
```
## 📁 Структура проекта
```
AnonBot/
├── main.py # Точка входа
├── bot.py # Основной файл бота
├── loader.py # Инициализация бота
├── dependencies.py # Система инъекции зависимостей
├── utils.py # Общие утилиты
├── requirements.txt # Зависимости
├── README.md # Документация
├── Dockerfile # Docker образ
├── .dockerignore # Исключения для Docker
├── .env_example # Пример переменных окружения
├── prometheus.yml # Конфигурация Prometheus
├── config/ # Конфигурация
│ ├── __init__.py
│ ├── config.py # Основная конфигурация
│ └── constants.py # Константы приложения
├── handlers/ # Обработчики сообщений
│ ├── __init__.py
│ ├── start.py # Команды /start, /help
│ ├── questions.py # Обработка анонимных вопросов
│ ├── answers.py # Обработка ответов
│ ├── admin.py # Админ функции
│ └── errors.py # Глобальная обработка ошибок
├── keyboards/ # Клавиатуры
│ ├── __init__.py
│ ├── inline.py # Inline клавиатуры
│ └── reply.py # Reply клавиатуры
├── models/ # Модели данных
│ ├── __init__.py
│ ├── user.py # Модель пользователя
│ ├── question.py # Модель вопроса
│ ├── user_block.py # Модель блокировки
│ └── user_settings.py # Модель настроек
├── services/ # Сервисы (реорганизованы по категориям)
│ ├── __init__.py
│ ├── utils.py # Общие утилиты
│ ├── auth/ # Авторизация и разрешения
│ │ ├── __init__.py
│ │ └── auth_new.py # Сервис авторизации с системой разрешений
│ ├── validation/ # Валидация входных данных
│ │ ├── __init__.py
│ │ └── input_validator.py # Централизованный валидатор
│ ├── business/ # Бизнес-логика
│ │ ├── __init__.py
│ │ ├── user_service.py # Сервис пользователей
│ │ ├── question_service.py # Сервис вопросов
│ │ ├── message_service.py # Сервис сообщений
│ │ └── pagination_service.py # Сервис пагинации
│ ├── infrastructure/ # Инфраструктурные сервисы
│ │ ├── __init__.py
│ │ ├── database.py # Работа с БД
│ │ ├── logger.py # Система логирования
│ │ ├── logging_decorators.py # Декораторы для автоматического логирования
│ │ ├── logging_utils.py # Утилиты для контекстного логирования
│ │ ├── metrics.py # Prometheus метрики
│ │ ├── http_server.py # HTTP сервер для метрик
│ │ └── pid_manager.py # Менеджер PID файлов
│ ├── rate_limiting/ # Rate limiting
│ │ ├── __init__.py
│ │ ├── rate_limit_config.py # Конфигурация rate limiting
│ │ ├── rate_limiter.py # Основной rate limiter
│ │ └── rate_limit_service.py # Сервис rate limiting
│ └── permissions/ # Система разрешений
│ ├── __init__.py
│ ├── base.py # Базовые классы
│ ├── registry.py # Реестр разрешений
│ ├── permissions.py # Стандартные разрешения
│ ├── decorators.py # Декораторы для проверки
│ └── init_permissions.py # Инициализация
├── examples/ # Примеры использования
│ └── dependency_injection_example.py
├── database/ # База данных
│ ├── __init__.py
│ ├── schema.sql # Схема БД
│ ├── crud.py # CRUD операции
│ └── examples.py # Примеры использования
├── middlewares/ # Middleware
│ ├── __init__.py
│ ├── rate_limit_middleware.py # Middleware для rate limiting
│ └── validation_middleware.py # Middleware для валидации данных
├── docs/ # Документация
└── logs/ # Логи приложения
```
### 🏗️ Архитектурные улучшения
Проект был реорганизован для улучшения структуры и масштабируемости:
#### 📁 Новая структура services
**До реорганизации:**
- Все сервисы в корне `services/`
- Смешанные категории (бизнес-логика + инфраструктура)
- Дублирование функциональности
**После реорганизации:**
- **`services/auth/`** - авторизация и разрешения
- **`services/business/`** - бизнес-логика (пользователи, вопросы, сообщения)
- **`services/infrastructure/`** - инфраструктурные сервисы (БД, логи, метрики)
- **`services/rate_limiting/`** - rate limiting компоненты
- **`services/permissions/`** - система разрешений (без изменений)
#### 📁 Новая структура config
**До реорганизации:**
- `config.py` и `constants.py` в корне проекта
**После реорганизации:**
- **`config/`** - папка для всех конфигурационных файлов
- **`config/config.py`** - основная конфигурация
- **`config/constants.py`** - константы приложения
#### ✅ Преимущества новой структуры
1. **Логическая группировка** - связанные сервисы в одних папках
2. **Разделение ответственности** - бизнес-логика отдельно от инфраструктуры
3. **Масштабируемость** - легко добавлять новые сервисы в нужные категории
4. **Читаемость** - понятно, где что находится
5. **Обратная совместимость** - старые импорты продолжают работать
#### 🔄 Обратная совместимость
Все импорты обновлены, но старые импорты продолжают работать благодаря `__init__.py` файлам:
```python
# Старый способ (все еще работает)
from services.database import DatabaseService
from config import config
# Новый способ (рекомендуется)
from services.infrastructure.database import DatabaseService
from config import config
```
### 🔍 Система валидации входных данных
Реализована централизованная система валидации всех входящих данных для обеспечения безопасности и стабильности:
#### 📋 Что валидируется
- **Telegram ID** - проверка диапазона и типа данных
- **Username** - валидация формата и допустимых символов
- **Текстовый контент** - проверка длины, HTML санитизация, защита от спама
- **Deep links** - валидация формата и длины
- **Callback data** - проверка безопасности и формата
- **Параметры пагинации** - валидация диапазонов
#### 🛡️ Безопасность
- **HTML санитизация** - автоматическое экранирование опасных тегов
- **Защита от спама** - проверка на повторяющиеся символы и слова
- **Валидация ID** - проверка корректности всех идентификаторов
- **Логирование** - полное логирование всех ошибок валидации с автоматическими декораторами
#### 🏗️ Архитектура валидации
```python
# Централизованный валидатор
from services.validation import InputValidator
validator = InputValidator()
# Валидация текста вопроса
result = validator.validate_question_text(text, max_length=1000)
if not result:
print(f"Ошибка: {result.error_message}")
else:
sanitized_text = result.sanitized_value
# Валидация callback data
result = validator.validate_callback_data(callback_data)
```
#### 🔄 Middleware валидации
Автоматическая валидация всех входящих данных через middleware:
```python
# ValidationMiddleware автоматически валидирует:
# - Все callback queries
# - Все сообщения
# - Telegram ID пользователей
# - Username (если есть)
# - Chat ID
```
#### ✅ Преимущества
1. **Безопасность** - защита от некорректных данных и атак
2. **Стабильность** - предотвращение ошибок от невалидных данных
3. **UX** - понятные сообщения об ошибках для пользователей
4. **Мониторинг** - полное логирование проблем валидации
5. **Централизация** - единая точка валидации для всего приложения
## 🎯 Как это работает
### Для пользователей:
1. **Регистрация**: Пользователь запускает бота командой `/start`
2. **Получение ссылки**: Бот генерирует персональную ссылку формата `t.me/bot_username?start=ref_{anonymous_id}`
3. **Публикация ссылки**: Пользователь делится ссылкой в социальных сетях
4. **Получение вопросов**: Друзья переходят по ссылке и задают анонимные вопросы
5. **Ответы**: Пользователь получает уведомления и может отвечать на вопросы
### Для отправителей вопросов:
1. **Переход по ссылке**: Отправитель переходит по персональной ссылке пользователя
2. **Задание вопроса**: Отправляет вопрос боту
3. **Анонимность**: Вопрос передается получателю анонимно
4. **Получение ответа**: Если получатель ответит, ответ будет показан
## 🔧 Команды бота
### Основные команды:
- `/start` - Запуск бота и получение персональной ссылки
- `/help` - Справка по использованию бота
### Админ команды:
- `/stats` - Показать статистику бота (только для админов)
## 👑 Админ панель
Администраторы имеют доступ к дополнительным функциям:
- 📊 **Статистика** - общая статистика бота, пользователей и вопросов
- 👥 **Пользователи** - список всех пользователей бота
- ❓ **Все вопросы** - статистика по всем вопросам
- 📢 **Рассылка** - функция рассылки (планируется)
- ⚙️ **Настройки** - просмотр текущих настроек бота
## 🔍 Система ролей и суперпользователи
Бот поддерживает трехуровневую систему ролей:
### 👑 Администраторы (admin)
- Определяются в конфигурации (`ADMINS` в `.env`)
- Имеют все права доступа
- Не могут быть изменены через базу данных
### 🔍 Суперпользователи (superuser)
- Определяются в базе данных (поле `is_superuser = TRUE`)
- Имеют расширенные права для модерации
- **Могут видеть информацию об авторах вопросов**
#### Особенности для суперпользователей:
**Отображение списка вопросов:**
```
10. ✅ #2 Вопрос от @username FirstName LastName
```
**Уведомления о новых вопросах:**
```
❓ Новый вопрос от @username FirstName LastName!
📝 Вопрос:
Текст вопроса...
📅 05.09.2025 23:27
```
### 👤 Обычные пользователи (user)
- Стандартные права доступа
- Видят анонимные вопросы без информации об авторах
### Назначение суперпользователя
Суперпользователей можно назначать через базу данных:
```sql
UPDATE users SET is_superuser = TRUE WHERE telegram_id = 123456789;
```
Или программно:
```python
from services.infrastructure.database import DatabaseService
async def make_superuser(telegram_id: int):
db_service = DatabaseService("database/anon_qna.db")
user = await db_service.get_user(telegram_id)
if user:
user.is_superuser = True
await db_service.update_user(user)
```
## 🔐 Система разрешений
AnonBot использует современную систему разрешений, построенную с соблюдением принципа открытости/закрытости (OCP):
### ✅ Преимущества новой системы
- **Открытость для расширения** - новые разрешения добавляются без изменения существующего кода
- **Закрытость для модификации** - существующий код не изменяется при добавлении новых разрешений
- **Типобезопасность** - использование классов вместо строк
- **Единая точка входа** - все проверки разрешений через один интерфейс
- **Удобные декораторы** - простое применение проверок разрешений
### 🎯 Стандартные разрешения
| Разрешение | Описание | Доступ |
|------------|----------|--------|
| `admin` | Права администратора | Только администраторы |
| `superuser` | Права суперпользователя | Только суперпользователи |
| `view_stats` | Просмотр статистики | Администраторы + суперпользователи |
| `admin_panel` | Доступ к админ панели | Администраторы + суперпользователи |
| `manage_users` | Управление пользователями | Администраторы + суперпользователи |
| `broadcast` | Рассылка сообщений | Только администраторы |
| `view_questions` | Просмотр вопросов | Все активные пользователи |
| `ask_questions` | Задавание вопросов | Все активные незабаненные пользователи |
| `answer_questions` | Ответы на вопросы | Все активные незабаненные пользователи |
### 🚀 Использование
#### С декораторами (рекомендуется)
```python
from services.permissions.decorators import require_permission
@router.message(Command("my_command"))
@require_permission("view_stats", "❌ У вас нет прав для выполнения этой команды.")
async def my_command_handler(message: Message):
# Логика обработчика
await message.answer("Команда выполнена!")
```
#### Готовые декораторы
```python
@require_permission("view_stats") # Конкретное разрешение
@require_admin() # Только администраторы
@require_superuser() # Только суперпользователи
@require_admin_or_superuser() # Администраторы или суперпользователи
@require_active_user() # Активные пользователи
@require_unbanned_user() # Незабаненные пользователи
```
#### Добавление нового разрешения
```python
# 1. Создаем класс разрешения
class MyCustomPermission(Permission):
async def check(self, user_id: int, database: DatabaseService, config) -> bool:
return user_id in config.ADMINS
# 2. Регистрируем разрешение
register_permission(MyCustomPermission())
# 3. Используем в обработчике
@require_permission("my_custom_permission")
async def my_handler(message: Message):
# Логика обработчика
pass
```
## 🛡️ Безопасность
- **Валидация**: Проверка всех входящих данных
- **Обработка ошибок**: Глобальная обработка ошибок с уведомлениями админов
- **Логирование**: Автоматическое логирование с декораторами, контекстная информация, FSM отслеживание
- **Система ролей**: Трехуровневая система доступа (админ/суперпользователь/пользователь)
- **Система разрешений**: Гибкая система разрешений с соблюдением принципа OCP
## 🏗️ Система инъекции зависимостей
AnonBot использует современную систему инъекции зависимостей, построенную на основе **MagicData** из aiogram 3.x. Это обеспечивает:
- **Тестируемость**: Легко мокать зависимости в тестах
- **Читаемость**: Явные зависимости в сигнатурах функций
- **Гибкость**: Легко заменять реализации сервисов
- **Обратная совместимость**: Старый код продолжает работать
### Доступные сервисы
1. **DatabaseService** - работа с базой данных, CRUD операции
2. **AuthService** - авторизация, проверка прав, управление ролями
3. **InputValidator** - централизованная валидация всех входных данных
4. **UtilsService** - форматирование данных, утилиты
5. **RateLimitService** - управление rate limiting, статистика
6. **Config** - доступ к конфигурации приложения
### Быстрый старт с DI
```python
# Подключение в loader.py
from dependencies import DependencyMiddleware, get_dependencies
async def init_dispatcher() -> Dispatcher:
dp = Dispatcher(storage=storage)
# Инициализируем зависимости
deps = get_dependencies()
await deps.init()
# Добавляем middleware
dp.update.middleware(DependencyMiddleware(deps))
return dp
# Использование в обработчиках
from dependencies import inject_start_services, inject_question_services, inject_answer_services
from services.infrastructure.database import DatabaseService
from services.auth.auth_new import AuthService
from services.validation import InputValidator
@router.message(Command("start"))
@inject_start_services
async def cmd_start(
message: Message,
user_service: UserService,
auth: AuthService,
utils: UtilsService,
message_service: MessageService,
validator: InputValidator
):
# Валидируем входные данные
user_id_validation = validator.validate_telegram_id(message.from_user.id)
if not user_id_validation:
await message.answer("❌ Ошибка: недопустимый ID пользователя")
return
# Используем сервисы без хардкода
is_admin = auth.is_admin(message.from_user.id)
user = await user_service.get_user_by_telegram_id(message.from_user.id)
```
### Способы инъекции
1. **Специализированные декораторы** (рекомендуется):
- `@inject_question_services` - для обработки вопросов
- `@inject_answer_services` - для обработки ответов
- `@inject_start_services` - для команды /start
- `@inject_link_services` - для кнопки "Моя ссылка"
- `@inject_main_menu_services` - для кнопки "Главное меню"
2. **Базовые декораторы**:
- `@inject_database` - только DatabaseService
- `@inject_auth` - только AuthService
- `@inject_utils` - только UtilsService
3. **Автоматически**: aiogram инжектит зависимости из middleware
4. **Обратная совместимость**: старые функции продолжают работать
### Примеры использования специализированных декораторов
#### Обработка вопросов
```python
@router.message(StateFilter(QuestionStates.waiting_for_question))
@inject_question_services
async def process_anonymous_question(
message: Message,
state: FSMContext,
question_service: QuestionService,
user_service: UserService,
message_service: MessageService,
validator: InputValidator
):
# Валидируем и обрабатываем вопрос
validation_result = validator.validate_question_text(message.text)
if not validation_result:
await message_service.send_message(message, "❌ Неверный формат вопроса")
return
# Создаем вопрос через сервис
question = await question_service.create_question(
message.from_user.id,
target_user_id,
validation_result.sanitized_value
)
```
#### Обработка ответов
```python
@router.message(StateFilter(AnswerStates.waiting_for_answer))
@inject_answer_services
async def process_new_answer(
message: Message,
state: FSMContext,
validator: InputValidator
):
# Валидируем ответ
validation_result = validator.validate_answer_text(message.text)
if not validation_result:
await message.answer("❌ Неверный формат ответа")
return
# Сохраняем ответ
# ... логика сохранения
```
### Локальная нумерация вопросов
#### Отображение вопросов с локальными номерами
```python
# В модели Question добавлен метод get_display_number()
def get_display_number(self) -> int:
"""Получить номер вопроса для отображения (приоритет user_question_number)"""
return self.user_question_number if self.user_question_number is not None else self.id
# В обработчиках используется локальная нумерация
questions_text += f"{i}. {emoji} #{question.get_display_number()}"
```
#### Автоматическая нумерация через триггеры БД
```sql
-- Триггер для автоматического вычисления номера при создании
CREATE TRIGGER calculate_user_question_number
AFTER INSERT ON questions
FOR EACH ROW
WHEN NEW.user_question_number IS NULL
BEGIN
UPDATE questions
SET user_question_number = (
SELECT COALESCE(MAX(user_question_number), 0) + 1
FROM questions q2
WHERE q2.to_user_id = NEW.to_user_id
AND q2.status != 'deleted'
)
WHERE id = NEW.id;
END;
-- Триггер для пересчета номеров при удалении
CREATE TRIGGER recalculate_user_question_numbers_on_delete
AFTER UPDATE ON questions
FOR EACH ROW
WHEN NEW.status = 'deleted' AND OLD.status != 'deleted'
BEGIN
UPDATE questions
SET user_question_number = user_question_number - 1
WHERE to_user_id = NEW.to_user_id
AND user_question_number > OLD.user_question_number
AND status != 'deleted';
UPDATE questions
SET user_question_number = NULL
WHERE id = NEW.id;
END;
```
#### Обработка команд
```python
@router.message(Command("start"))
@inject_start_services
async def cmd_start(
message: Message,
state: FSMContext,
user_service: UserService,
auth: AuthService,
utils: UtilsService,
message_service: MessageService,
validator: InputValidator
):
# Создаем или обновляем пользователя
user = await user_service.create_or_update_user(message.from_user, message.chat.id)
# Проверяем права
is_admin = auth.is_admin(user.telegram_id)
# Отправляем приветствие
await message_service.send_message(message, welcome_text, keyboard)
```
### Преимущества специализированных декораторов
✅ **Нет проблем с `dispatcher`** - aiogram не передает лишние параметры
✅ **Меньше зависимостей** - инжектируются только нужные сервисы
✅ **Лучшая производительность** - меньше объектов создается
✅ **Более явный код** - видно, какие зависимости используются
✅ **Легче тестировать** - меньше моков нужно создавать
### Тестирование
Система DI значительно упрощает тестирование:
```python
# Создание тестовых зависимостей
@pytest.fixture
async def test_dependencies():
deps = Dependencies()
deps._database = AsyncMock() # Мокаем БД
deps._auth = MagicMock() # Мокаем авторизацию
return deps
# Тестирование обработчиков
@pytest.mark.asyncio
async def test_cmd_start(test_dependencies):
# Настраиваем моки
test_dependencies._user_service.get_user_by_telegram_id.return_value = mock_user
test_dependencies._auth.is_admin.return_value = False
# Тестируем обработчик
result = await cmd_start(
message,
state,
user_service=test_dependencies.user_service,
auth=test_dependencies.auth,
utils=test_dependencies.utils,
message_service=test_dependencies.message_service,
validator=test_dependencies.validator
)
# Проверяем результат
assert result is not None
```
Подробная документация: [DI_SETUP.md](DI_SETUP.md)
## 📊 База данных
Бот использует SQLite для хранения данных:
### Таблицы:
- **users**: Информация о пользователях (ID, имя, ссылка, статус, права суперпользователя)
- **questions**: Вопросы и ответы (текст, статус, анонимность, локальная нумерация)
- **user_blocks**: Блокировки пользователей
- **user_settings**: Настройки пользователей (уведомления, язык)
### Особенности:
- **Внешние ключи**: Связи между таблицами
- **Триггеры**: Автоматическое обновление timestamps и нумерация вопросов
- **Индексы**: Оптимизация запросов, включая индексы для локальной нумерации
- **CRUD операции**: Полный набор операций для каждой таблицы
- **Локальная нумерация**: Каждый пользователь видит свои вопросы с номерами #1, #2, #3...
### Автоматическая нумерация вопросов:
- **Триггер `calculate_user_question_number`**: Автоматически присваивает номер при создании вопроса
- **Триггер `recalculate_user_question_numbers_on_delete`**: Пересчитывает номера при удалении вопроса
- **Удаленные вопросы**: Не участвуют в нумерации (status = 'deleted')
- **Уникальные номера**: Гарантируется уникальность номеров в рамках каждого пользователя
### Схема:
Схема базы данных находится в файле `database/schema.sql`
## 🔧 Настройка
Все настройки находятся в файле `.env`:
- `BOT_TOKEN` - токен бота (обязательно)
- `ADMINS` - список ID администраторов
- `DATABASE_PATH` - путь к файлу базы данных
- `DEBUG` - режим отладки
- `MAX_QUESTION_LENGTH` - максимальная длина вопроса
- `MAX_ANSWER_LENGTH` - максимальная длина ответа
#### Настройки Rate Limiting:
- `RATE_LIMIT_ENV` - окружение (development/production/strict)
- `RATE_LIMIT_MESSAGES_PER_SECOND` - сообщений в секунду на чат
- `RATE_LIMIT_BURST_LIMIT` - максимум сообщений подряд
- `RATE_LIMIT_RETRY_MULTIPLIER` - множитель для задержки при retry
- `RATE_LIMIT_MAX_RETRY_DELAY` - максимальная задержка между попытками
- `RATE_LIMIT_MAX_RETRIES` - максимальное количество повторных попыток
## 🚀 Развертывание
### Локальный запуск:
```bash
python main.py
```
### Docker (планируется):
```bash
docker build -t anonbot .
docker run -d --name anonbot anonbot
```
### VPS/Сервер:
1. Загрузите код на сервер
2. Установите зависимости: `pip install -r requirements.txt`
3. Настройте `.env` файл
4. **Для обновления существующей базы данных** (если нужно добавить поле `is_superuser`):
```bash
python3 -c "
import asyncio
import aiosqlite
async def migrate():
async with aiosqlite.connect('database/anon_qna.db') as conn:
await conn.execute('ALTER TABLE users ADD COLUMN is_superuser BOOLEAN DEFAULT FALSE')
await conn.execute('CREATE INDEX IF NOT EXISTS idx_users_is_superuser ON users(is_superuser)')
await conn.commit()
print('Миграция завершена!')
asyncio.run(migrate())
"
```
5. Запустите: `python main.py`
6. Рекомендуется использовать systemd или supervisor для автозапуска
## 📝 Система логирования
В проекте настроена продвинутая система логирования с использованием библиотеки **loguru** и автоматических декораторов. Логи выводятся в stderr для корректной работы в Docker контейнерах.
### Основные компоненты
- **services/infrastructure/logger.py** - основная настройка системы логирования
- **services/infrastructure/logging_decorators.py** - декораторы для автоматического логирования
- **services/infrastructure/logging_utils.py** - утилиты для контекстного логирования
- **loguru** - библиотека для логирования (уже добавлена в requirements.txt)
### Уровни логирования
- **INFO** - основная информация о работе бота
- **WARNING** - предупреждения о потенциальных проблемах
- **ERROR** - ошибки, требующие внимания
### Формат логов
```
2024-01-15 10:30:45 | INFO | bot:main:25 - 🚀 Запуск бота в режиме polling
2024-01-15 10:30:45 | INFO | loader:init_bot:28 - 🤖 Инициализация Telegram бота
2024-01-15 10:30:45 | INFO | loader:init_bot:33 - ✅ Бот успешно инициализирован
```
### 🎯 Автоматические декораторы логирования
Система включает в себя набор декораторов для автоматического логирования:
#### 1. Основные декораторы
**`@log_function_call`** - логирование входа/выхода из функций
```python
@log_function_call(log_params=True, log_result=True)
async def create_question(self, from_user_id: int, to_user_id: int, message_text: str):
# Автоматически логирует вход с параметрами и выход с результатом
```
**`@log_business_event`** - логирование бизнес-событий
```python
@log_business_event("create_question", log_params=True, log_result=True)
async def create_question(self, ...):
# Логирует бизнес-событие с контекстом
```
**`@log_fsm_transition`** - логирование FSM переходов
```python
@log_fsm_transition(to_state="waiting_for_answer")
async def answer_question_callback(callback: CallbackQuery, state: FSMContext):
# Логирует переходы между состояниями FSM
```
#### 2. Оптимизированные декораторы
**`@log_middleware`** - тихое логирование для middleware
```python
@log_middleware(log_params=True, log_result=False)
async def __call__(self, handler, event, data):
# Логирует только ошибки, вход/выход в DEBUG режиме
```
**`@log_utility`** - декоратор для служебных функций
```python
@log_utility
def _has_attachments(message: Message) -> bool:
# Логирует только ошибки
```
#### 3. Контекстное логирование
**`LoggingContext`** - контекстное логирование с дополнительной информацией
```python
context = get_logging_context(__name__)
context.add_context("user_id", user_id)
context.log_info("Пользователь выполнил действие")
```
**Специальные функции** для бизнес-событий:
```python
log_question_created(logger, question_id, from_user_id, to_user_id)
log_user_created(logger, user_id, username)
log_user_blocked(logger, user_id, reason)
```
### Покрытие логированием
#### 1. Запуск и инициализация
- ✅ Инициализация бота
- ✅ Инициализация диспетчера
- ✅ Инициализация базы данных
- ✅ Регистрация обработчиков
- ✅ Уведомления администраторов
#### 2. База данных (CRUD операции)
- ✅ Создание пользователей
- ✅ Создание вопросов
- ✅ Обновление вопросов
- ✅ Инициализация БД
#### 3. Обработчики команд
- ✅ Команда /start
- ✅ Обработка deep links
- ✅ Создание/обновление пользователей
#### 4. Бизнес-логика
- ✅ Отправка ответов авторам
- ✅ Обработка ошибок
- ✅ Валидация данных
#### 5. Системные события
- ✅ Ошибки в обработчиках
- ✅ Очистка ресурсов
- ✅ Остановка бота
#### 6. FSM состояния
- ✅ Переходы между состояниями
- ✅ Обработка FSM событий
- ✅ Отслеживание пользовательских сессий
### Использование в коде
#### Импорт логгера и декораторов
```python
from services.infrastructure.logger import get_logger
from services.infrastructure.logging_decorators import (
log_function_call, log_business_event, log_fsm_transition,
log_middleware, log_utility
)
from services.infrastructure.logging_utils import (
log_user_action, log_business_operation, log_question_created
)
logger = get_logger(__name__)
```
#### Примеры использования декораторов
```python
# Бизнес-события
@log_business_event("create_question", log_params=True, log_result=True)
async def create_question(self, from_user_id: int, to_user_id: int, message_text: str):
# Автоматически логирует создание вопроса
pass
# FSM переходы
@log_fsm_transition(to_state="waiting_for_answer")
async def answer_question_callback(callback: CallbackQuery, state: FSMContext):
# Логирует переход в состояние ответа
pass
# Middleware (тихое логирование)
@log_middleware(log_params=True, log_result=False)
async def __call__(self, handler, event, data):
# Логирует только ошибки
pass
# Служебные функции
@log_utility
def _has_attachments(message: Message) -> bool:
# Логирует только ошибки
pass
```
#### Контекстное логирование
```python
# Создание контекста
context = get_logging_context(__name__)
context.add_context("user_id", user_id)
context.add_context("question_id", question_id)
context.log_info("Пользователь ответил на вопрос")
# Специальные функции для бизнес-событий
log_question_created(logger, question_id, from_user_id, to_user_id)
log_user_created(logger, user_id, username)
log_user_blocked(logger, user_id, reason)
```
#### Традиционное логирование
```python
# Информационные сообщения
logger.info("🚀 Запуск бота в режиме polling")
logger.info(f"👤 Создание пользователя: {user.telegram_id} ({user.first_name})")
# Предупреждения
logger.warning("⚠️ Список администраторов пуст")
logger.warning(f"⚠️ Не удалось отправить уведомление админу {admin_id}: {e}")
# Ошибки
logger.error(f"💥 Ошибка при запуске бота: {e}")
logger.error(f"💥 Ошибка в обработчике /start: {e}")
```
### Docker интеграция
Логи настроены для вывода в stderr, что обеспечивает корректную работу в Docker:
```dockerfile
# В Dockerfile
CMD ["python", "main.py"]
```
```bash
# Просмотр логов в Docker
docker logs
```
### Файловое логирование (DEBUG режим)
В режиме отладки логи также сохраняются в файлы:
- **logs/bot.log** - основные логи
- Ротация: 10 MB
- Хранение: 7 дней
- Сжатие: zip
### ⚡ Производительность и оптимизация
#### Тихие декораторы
Для предотвращения избыточного логирования используются тихие декораторы:
- **`@log_middleware`** - для middleware (логирует только ошибки)
- **`@log_utility`** - для служебных функций (логирует только ошибки)
- **`quiet=True`** - параметр для полного отключения логирования входа/выхода
#### Уровни логирования
- **INFO** - бизнес-события и важные операции
- **DEBUG** - детальная информация (только в DEBUG режиме)
- **WARNING** - предупреждения
- **ERROR** - ошибки (всегда логируются)
#### Контекстная информация
Декораторы автоматически извлекают контекстную информацию:
- `user_id` - ID пользователя
- `question_id` - ID вопроса
- `page` - номер страницы
- `status` - статус операции
#### Примеры оптимизированного логирования
```python
# Middleware - тихое логирование
@log_middleware(log_params=True, log_result=False)
async def __call__(self, handler, event, data):
# Логирует только ошибки, вход/выход в DEBUG режиме
pass
# Служебные функции - только ошибки
@log_utility
def _has_attachments(message: Message) -> bool:
# Логирует только ошибки
pass
# Бизнес-функции - полное логирование
@log_business_event("create_question", log_params=True, log_result=True)
async def create_question(self, ...):
# Полное логирование для важных операций
pass
```
### Мониторинг
#### Ключевые метрики для мониторинга
1. **Запуск/остановка бота**
- `🚀 Запуск бота в режиме polling`
- `🛑 Бот остановлен`
2. **Пользователи**
- `👤 Создание пользователя`
- `👤 Обновление существующего пользователя`
3. **Вопросы и ответы**
- `❓ Создание вопроса`
- `📝 Обновление вопроса`
- `📤 Отправка ответа`
4. **Ошибки**
- `💥 Ошибка в обработчике`
- `⚠️ Предупреждения`
#### Алерты
Рекомендуется настроить алерты на:
- ERROR уровень логов
- Отсутствие логов более 5 минут
- Частые ошибки в обработчиках
### Настройка уровней
Уровень логирования настраивается через переменную окружения:
```bash
# В .env файле
DEBUG=true # DEBUG уровень
DEBUG=false # INFO уровень (по умолчанию)
```
### Производительность
- Логирование асинхронное
- Минимальное влияние на производительность
- Эмодзи в логах для быстрого визуального поиска
- Структурированный формат для парсинга
## 🤝 Вклад в проект
1. Fork репозитория
2. Создайте feature branch
3. Внесите изменения
4. Создайте Pull Request
## 📄 Лицензия
MIT License
## 🆘 Поддержка
Если у вас возникли проблемы:
1. Проверьте логи бота
2. Убедитесь в правильности настройки `.env`
3. Проверьте права доступа к файлам
4. Обратитесь к администратору
### Дополнительная документация:
- [Руководство по суперпользователям](SUPERUSER_DISPLAY_FEATURE.md) - подробное описание системы ролей и функционала для суперпользователей
- [Настройка Dependency Injection](DI_SETUP.md) - подробное руководство по системе инъекции зависимостей
- [Примеры использования DI](examples/dependency_injection_example.py) - практические примеры использования системы инъекции зависимостей
## 📈 Prometheus метрики
AnonBot поддерживает экспорт метрик в формате Prometheus для мониторинга и анализа производительности.
### Эндпоинты
- **http://localhost:8081/metrics** - экспорт метрик Prometheus
- **http://localhost:8081/health** - проверка здоровья бота
- **http://localhost:8081/ready** - готовность к работе (readiness probe)
- **http://localhost:8081/status** - информация о процессе (PID, uptime, использование ресурсов)
- **http://localhost:8081/** - информация о сервисе
### Доступные метрики
#### Информационные метрики
- `anon_bot_info` - Информация о боте (версия, сервис)
#### Счетчики сообщений
- `anon_bot_messages_total` - Общее количество обработанных сообщений
- Метки: `message_type`, `status`
#### Счетчики вопросов
- `anon_bot_questions_total` - Общее количество вопросов
- Метки: `status` (created, rejected, deleted)
#### Счетчики ответов
- `anon_bot_answers_total` - Общее количество ответов
- Метки: `status` (sent, edited, delivered, delivery_failed)
#### Счетчики пользователей
- `anon_bot_users_total` - Общее количество пользователей
- Метки: `action` (created, updated)
#### Счетчики ошибок
- `anon_bot_errors_total` - Общее количество ошибок
- Метки: `error_type`, `component`
#### HTTP метрики
- `anon_bot_http_requests_total` - Общее количество HTTP запросов
- Метки: `method`, `endpoint`, `status_code`
- `anon_bot_http_request_duration_seconds` - Время обработки HTTP запросов
- Метки: `method`, `endpoint`
#### Время обработки
- `anon_bot_message_processing_seconds` - Время обработки сообщений
- Метки: `message_type`
- `anon_bot_question_processing_seconds` - Время обработки вопросов
- `anon_bot_answer_processing_seconds` - Время обработки ответов
#### Gauge метрики
- `anon_bot_active_users` - Количество активных пользователей
- `anon_bot_active_questions` - Количество активных вопросов
### Настройка Prometheus
Добавьте в конфигурацию Prometheus (`prometheus.yml`):
```yaml
scrape_configs:
- job_name: 'anon-bot'
static_configs:
- targets: ['localhost:8081']
metrics_path: '/metrics'
scrape_interval: 30s
```
### Примеры запросов PromQL
#### Количество сообщений в секунду
```promql
rate(anon_bot_messages_total[5m])
```
#### Количество ошибок в секунду
```promql
rate(anon_bot_errors_total[5m])
```
#### Время обработки сообщений (95-й процентиль)
```promql
histogram_quantile(0.95, rate(anon_bot_message_processing_seconds_bucket[5m]))
```
#### Количество активных пользователей
```promql
anon_bot_active_users
```
### Мониторинг в Docker
При запуске в Docker убедитесь, что порт 8081 доступен:
```yaml
ports:
- "8081:8081"
```
### Алерты
Рекомендуется настроить алерты на:
1. **Высокий уровень ошибок**
```promql
rate(anon_bot_errors_total[5m]) > 0.1
```
2. **Медленную обработку**
```promql
histogram_quantile(0.95, rate(anon_bot_message_processing_seconds_bucket[5m])) > 5
```
3. **Недоступность сервиса**
```promql
up{job="anon-bot"} == 0
```
### Безопасность
Эндпоинты метрик не требуют аутентификации. В продакшене рекомендуется:
- Ограничить доступ к эндпоинтам через firewall
- Использовать reverse proxy с аутентификацией
- Настроить TLS для HTTPS
## 🐳 Docker
### Сборка образа
```bash
docker build -t anon-bot .
```
### Запуск контейнера
```bash
docker run -d \
--name anon-bot \
--restart unless-stopped \
-p 8081:8081 \
-v $(pwd)/database:/app/database \
-v $(pwd)/logs:/app/logs \
-e BOT_TOKEN=your_bot_token_here \
-e ADMINS=123456789,987654321 \
-e DEBUG=false \
anon-bot
```
### Управление контейнером
```bash
# Просмотр логов
docker logs anon-bot
# Остановка контейнера
docker stop anon-bot
# Запуск контейнера
docker start anon-bot
# Удаление контейнера
docker rm anon-bot
# Перезапуск контейнера
docker restart anon-bot
```
### Переменные окружения
Все переменные окружения из `.env_example` можно передать через `-e`:
```bash
docker run -d \
--name anon-bot \
-p 8081:8081 \
-e BOT_TOKEN=your_token \
-e ADMINS=123456789 \
-e DEBUG=false \
-e MAX_QUESTION_LENGTH=1000 \
-e MAX_ANSWER_LENGTH=2000 \
anon-bot
```
### Volumes
- `./database:/app/database` - персистентное хранение базы данных
- `./logs:/app/logs` - персистентное хранение логов
### Порты
- `8081:8081` - порт для метрик и health check
### Health Check
Контейнер включает встроенный health check:
```bash
# Проверка статуса
docker inspect --format='{{.State.Health.Status}}' anon-bot
# Просмотр деталей health check
docker inspect anon-bot | jq '.[0].State.Health'
```
**Параметры health check:**
- **Интервал проверки**: 30 секунд
- **Таймаут**: 10 секунд
- **Период запуска**: 60 секунд (время на инициализацию)
- **Количество попыток**: 3
- **Команда проверки**: `curl -f http://localhost:8081/health`
**Статусы health check:**
- `starting` - контейнер запускается
- `healthy` - контейнер здоров
- `unhealthy` - контейнер нездоров
## 🚦 Rate Limiting
AnonBot включает комплексную систему rate limiting для предотвращения ошибок Flood Control в Telegram Bot API. Система автоматически ограничивает скорость отправки сообщений и обрабатывает ошибки с повторными попытками.
### Рекомендуемые настройки на основе лимитов Telegram API
Система настроена с учетом официальных лимитов Telegram Bot API:
- **1 сообщение в секунду** в личных чатах
- **20 сообщений в минуту** в групповых чатах (0.33 в секунду)
- **30 запросов в секунду** глобально
Настройки по умолчанию используют консервативные значения (50% от лимитов) для обеспечения стабильной работы.
### Компоненты системы
#### 1. Конфигурация (`services/rate_limit_config.py`)
- **RateLimitSettings**: Основные настройки rate limiting
- **Конфигурации для разных окружений**: development, production, strict
- **Адаптивная конфигурация**: Автоматическая настройка на основе уровня ошибок
#### 2. Rate Limiter (`services/rate_limiter.py`)
- **ChatRateLimiter**: Ограничения для конкретного чата
- **GlobalRateLimiter**: Глобальные ограничения для всех чатов
- **RetryHandler**: Обработка повторных попыток с экспоненциальной задержкой
- **TelegramRateLimiter**: Основной класс, объединяющий все компоненты
#### 3. Сервис (`services/rate_limit_service.py`)
- **RateLimitService**: Высокоуровневый сервис для управления rate limiting
- **Статистика**: Отслеживание успешных/неудачных запросов
- **Адаптация**: Автоматическая настройка конфигурации
#### 4. Middleware (`middlewares/rate_limit_middleware.py`)
- **RateLimitMiddleware**: Автоматическое применение rate limiting ко всем сообщениям
- **Прозрачная интеграция**: Минимальные изменения в существующем коде
#### 5. Validation Middleware (`middlewares/validation_middleware.py`)
- **ValidationMiddleware**: Автоматическая валидация всех входящих данных
- **Безопасность**: Защита от некорректных данных и атак
- **Логирование**: Оптимизированное логирование с тихими декораторами для middleware
### Настройка
#### Переменные окружения
Добавьте следующие переменные в ваш `.env` файл:
```env
# Окружение для rate limiting (development/production/strict)
RATE_LIMIT_ENV=production
# Основные настройки rate limiting
RATE_LIMIT_MESSAGES_PER_SECOND=0.5
RATE_LIMIT_BURST_LIMIT=2
RATE_LIMIT_RETRY_MULTIPLIER=1.5
RATE_LIMIT_MAX_RETRY_DELAY=30.0
RATE_LIMIT_MAX_RETRIES=3
# Задержки для разных типов сообщений
RATE_LIMIT_VOICE_DELAY=2.0
RATE_LIMIT_MEDIA_DELAY=1.5
RATE_LIMIT_TEXT_DELAY=1.0
# Множители для разных типов чатов
RATE_LIMIT_PRIVATE_MULTIPLIER=1.0
RATE_LIMIT_GROUP_MULTIPLIER=0.8
RATE_LIMIT_CHANNEL_MULTIPLIER=0.6
# Глобальные ограничения
RATE_LIMIT_GLOBAL_MESSAGES_PER_SECOND=10.0
RATE_LIMIT_GLOBAL_BURST_LIMIT=20
```
#### Конфигурации по умолчанию
**Production (по умолчанию)**
- 0.5 сообщений в секунду на чат (50% от лимита Telegram API)
- Максимум 2 сообщения подряд
- 3 повторные попытки при ошибках
- Максимальная задержка 30 секунд
- 20 глобальных запросов в секунду (из 30 доступных)
**Development**
- 0.8 сообщений в секунду на чат (80% от лимита для тестирования)
- Максимум 3 сообщения подряд
- 2 повторные попытки при ошибках
- Максимальная задержка 15 секунд
**Strict**
- 0.3 сообщений в секунду на чат (30% от лимита для максимальной стабильности)
- Максимум 1 сообщение подряд
- 5 повторных попыток при ошибках
- Максимальная задержка 60 секунд
- 10 глобальных запросов в секунду (консервативные настройки)
### Использование
#### Автоматическое использование (рекомендуется)
Rate limiting и валидация автоматически применяются ко всем сообщениям через middleware. Никаких изменений в коде не требуется.
**ValidationMiddleware** автоматически валидирует:
- Все callback queries
- Все сообщения
- Telegram ID пользователей
- Username (если есть)
- Chat ID
#### Ручное использование
```python
from services.rate_limiting.rate_limit_service import RateLimitService
from dependencies import get_rate_limit_service
# Получение сервиса через DI
rate_limit_service = get_rate_limit_service()
# Отправка сообщения с rate limiting
result = await rate_limit_service.send_with_rate_limit(
bot.send_message,
chat_id=user_id,
text="Привет!"
)
```
#### Прямое использование rate limiter
```python
from services.rate_limiting.rate_limiter import send_with_rate_limit
# Отправка с автоматическим rate limiting
result = await send_with_rate_limit(
bot.send_message,
chat_id=user_id,
text="Привет!"
)
```
#### Ручное использование валидатора
```python
from services.validation import InputValidator
from dependencies import get_validator
# Получение валидатора через DI
validator = get_validator()
# Валидация текста вопроса
result = validator.validate_question_text(text, max_length=1000)
if not result:
print(f"Ошибка: {result.error_message}")
else:
sanitized_text = result.sanitized_value
# Валидация callback data
result = validator.validate_callback_data(callback_data)
if not result:
await callback.answer("❌ Неверные данные", show_alert=True)
return
```
### Административные функции
Доступ к управлению rate limiting осуществляется через админскую панель:
1. **Перейти в админку**: `/admin`
2. **Нажать кнопку "🚦 Rate Limiting"**
3. **Выбрать нужное действие**:
- **📊 Статистика Rate Limiting** - показывает подробную статистику:
- Общее количество запросов
- Процент успеха/ошибок
- Количество RetryAfter ошибок
- Среднее время ожидания
- **🔄 Сбросить статистику** - сбрасывает всю статистику rate limiting
- **⚙️ Адаптировать конфигурацию** - адаптирует настройки на основе текущей производительности
**Важно**: Доступ к функциям rate limiting имеют только администраторы бота (не суперпользователи).
### Мониторинг
#### Логирование
Система логирует:
- Rate limiting события (DEBUG уровень)
- RetryAfter ошибки (WARNING уровень)
- Критические ошибки (ERROR уровень)
#### Статистика
RateLimitService отслеживает:
- Общее количество запросов
- Успешные/неудачные запросы
- Типы ошибок (RetryAfter, API ошибки)
- Время ожидания
#### Адаптивная конфигурация
Система автоматически адаптирует настройки:
- При >10% ошибок: ужесточает ограничения
- При <1% ошибок: ослабляет ограничения
- Требует минимум 100 запросов для адаптации
### Интеграция с DI
Rate limiting полностью интегрирован в систему инъекции зависимостей:
```python
# В обработчиках
async def some_handler(
message: Message,
rate_limit_service: RateLimitService
):
# rate_limit_service автоматически инжектируется
pass
```
### Архитектурные особенности
#### Соблюдение принципов
1. **Single Responsibility**: Каждый компонент отвечает за свою задачу
2. **Open/Closed**: Легко расширяется новыми типами ограничений
3. **Dependency Inversion**: Зависит от абстракций, а не от конкретных реализаций
#### Производительность
- Минимальные накладные расходы
- Эффективное управление памятью
- Асинхронная обработка
#### Надежность
- Обработка всех типов ошибок Telegram API
- Экспоненциальная задержка при повторных попытках
- Автоматическое восстановление после ошибок
### Устранение неполадок
#### Высокий процент ошибок
1. Проверьте статистику: `/ratelimit_stats`
2. Адаптируйте конфигурацию: `/adapt_ratelimit`
3. При необходимости ужесточите настройки в `.env`
#### Медленная отправка сообщений
1. Проверьте настройки `RATE_LIMIT_MESSAGES_PER_SECOND`
2. Увеличьте значение для более быстрой отправки
3. Убедитесь, что не превышаете лимиты Telegram API
#### Проблемы с интеграцией
1. Убедитесь, что middleware зарегистрирован в `loader.py`
2. **Ошибка `TypeError: got an unexpected keyword argument 'dispatcher'`**:
- **Причина**: aiogram 3.x передает `dispatcher` во все обработчики сообщений, но `@inject_all` не обрабатывает его правильно
- **Решение**: Используйте специализированные декораторы вместо `@inject_all`:
```python
# ❌ Неправильно
@inject_all
async def process_question(message: Message, dispatcher, ...):
# ✅ Правильно
@inject_question_services
async def process_question(message: Message, question_service: QuestionService, ...):
```
- **Преимущества**: Нет проблем с `dispatcher`, меньше зависимостей, лучшая производительность
3. Проверьте, что все зависимости корректно импортированы
4. Проверьте логи на наличие ошибок инициализации
## 🔮 Планы развития
- [x] **Система суперпользователей** - расширенные права для модерации с отображением информации об авторах
- [x] **Система инъекции зависимостей** - современная архитектура с DI для лучшей тестируемости
- [x] **Система разрешений** - гибкая система разрешений с соблюдением принципа OCP
- [x] **Prometheus метрики** - мониторинг производительности и ошибок
- [x] **Rate limiting** - защита от спама и DDoS с автоматической адаптацией
- [x] **Реорганизация структуры проекта** - улучшенная архитектура с логической группировкой сервисов
- [x] **Локальная нумерация вопросов** - каждый пользователь видит свои вопросы с номерами #1, #2, #3... вместо глобальных ID
- [ ] **Unit-тесты** - полное покрытие тестами с использованием DI
- [ ] **Кэширование Redis** - оптимизация производительности
- [ ] Рассылка сообщений
- [ ] Экспорт данных
- [ ] Веб-интерфейс для админов
- [ ] Поддержка медиафайлов в вопросах
- [ ] Категории вопросов
- [ ] Модерация контента
- [ ] Аналитика и отчеты
## 📝 Changelog
### v1.7.0 - Продвинутая система логирования (2025-01-27)
#### ✨ Новые возможности
- **Автоматические декораторы логирования** - `@log_function_call`, `@log_business_event`, `@log_fsm_transition`
- **Контекстное логирование** - `LoggingContext` с дополнительной информацией
- **Оптимизированные декораторы** - `@log_middleware`, `@log_utility` для предотвращения избыточного логирования
- **FSM отслеживание** - автоматическое логирование переходов между состояниями
- **Специальные функции** - `log_question_created`, `log_user_created`, `log_user_blocked`
- **Тихие декораторы** - предотвращение рекурсивного логирования в middleware
#### 🔧 Улучшения
- **100% покрытие логированием** - все функции теперь логируются автоматически
- **Улучшенная производительность** - оптимизированное логирование для middleware
- **Детальная диагностика** - полная трассировка выполнения функций
- **Контекстная информация** - автоматическое извлечение user_id, question_id и других параметров
#### 📁 Новые файлы
- `services/infrastructure/logging_decorators.py` - декораторы для автоматического логирования
- `services/infrastructure/logging_utils.py` - утилиты для контекстного логирования
### v1.6.0 - Локальная нумерация вопросов (2025-01-27)
#### ✨ Новые возможности
- **Локальная нумерация вопросов**: Каждый пользователь теперь видит свои вопросы с номерами #1, #2, #3... вместо глобальных ID
- **Автоматическая нумерация**: Триггеры БД автоматически присваивают и пересчитывают номера вопросов
- **Умная нумерация**: Удаленные вопросы не участвуют в нумерации, номера автоматически пересчитываются при удалении
#### 🔧 Технические изменения
- **Новое поле БД**: `user_question_number` в таблице `questions`
- **Триггеры БД**:
- `calculate_user_question_number` - автоматическое вычисление номера при создании
- `recalculate_user_question_numbers_on_delete` - пересчет номеров при удалении
- **Индексы**: Оптимизированные индексы для быстрого поиска по локальным номерам
- **Модель Question**: Новый метод `get_display_number()` для получения номера для отображения
#### 🐛 Исправления
- **Отображение номеров**: Исправлена проблема с несоответствием номеров в тексте сообщений и на кнопках
- **Пагинация**: Обновлена для работы с локальными номерами
- **CRUD операции**: Обновлены для поддержки автоматической нумерации
#### 📊 Улучшения UX
- **Интуитивная нумерация**: Пользователи видят последовательные номера своих вопросов
- **Консистентность**: Номера в тексте и на кнопках всегда совпадают
- **Автоматизация**: Никаких ручных действий для поддержания нумерации