This commit is contained in:
270
docs/BROADCAST_SYSTEM.md
Normal file
270
docs/BROADCAST_SYSTEM.md
Normal file
@@ -0,0 +1,270 @@
|
||||
# Система рассылок с Redis очередями
|
||||
|
||||
## Обзор
|
||||
|
||||
Расширенная система массовых рассылок с поддержкой трех типов рассылки:
|
||||
- **ЛС пользователям** - массовая рассылка по личным сообщениям с отслеживанием заблокированных
|
||||
- **В канал** - отправка в Telegram канал
|
||||
- **В группу** - отправка в Telegram группу
|
||||
|
||||
## Основные возможности
|
||||
|
||||
### 1. Рассылка в личные сообщения
|
||||
|
||||
**Особенности:**
|
||||
- Использование Redis очередей для управления потоком сообщений
|
||||
- Автоматическое отслеживание пользователей, заблокировавших бота
|
||||
- Пакетная отправка с задержками для соблюдения лимитов Telegram
|
||||
- Детальная обработка ошибок (блокировка, деактивация аккаунта, etc.)
|
||||
- Автоматическое повторение при FloodWait ошибках
|
||||
|
||||
**Технические детали:**
|
||||
- Размер пакета: 30 сообщений
|
||||
- Задержка между пакетами: 1 секунда
|
||||
- Дополнительная задержка при FloodWait: 5 секунд + время из ошибки
|
||||
|
||||
### 2. Рассылка в канал/группу
|
||||
|
||||
**Особенности:**
|
||||
- Управление списком каналов и групп через админ-панель
|
||||
- Проверка прав бота перед добавлением канала
|
||||
- Возможность добавить описание для каждого канала
|
||||
- Активация/деактивация каналов
|
||||
|
||||
## Архитектура
|
||||
|
||||
### Модели данных
|
||||
|
||||
#### BroadcastChannel
|
||||
Хранит информацию о каналах и группах для рассылки:
|
||||
- `chat_id` - ID чата в Telegram
|
||||
- `chat_type` - тип (channel/group)
|
||||
- `title` - название
|
||||
- `username` - юзернейм (если есть)
|
||||
- `description` - описание
|
||||
- `is_active` - активен ли для рассылок
|
||||
- `added_by` - кто добавил
|
||||
|
||||
#### BlockedUser
|
||||
Отслеживание заблокированных/недоступных пользователей:
|
||||
- `telegram_id` - ID пользователя
|
||||
- `error_type` - тип ошибки (blocked_bot, deactivated, not_found, etc.)
|
||||
- `error_message` - полное сообщение об ошибке
|
||||
- `first_blocked_at` - первая попытка
|
||||
- `last_attempt_at` - последняя попытка
|
||||
- `attempt_count` - количество неудачных попыток
|
||||
- `is_active` - активна ли блокировка
|
||||
|
||||
#### BroadcastLog
|
||||
История рассылок:
|
||||
- `broadcast_type` - тип (direct/channel/group)
|
||||
- `target_id` - ID канала/группы (для соответствующих типов)
|
||||
- `message_type` - тип сообщения
|
||||
- `message_text` - текст
|
||||
- `file_id` - ID файла (если есть)
|
||||
- Статистика: `total_recipients`, `success_count`, `failed_count`, `blocked_count`
|
||||
- `created_by` - кто запустил
|
||||
- `started_at`, `completed_at` - временные метки
|
||||
- `status` - статус (pending/in_progress/completed/failed)
|
||||
|
||||
### Сервисы
|
||||
|
||||
#### BroadcastService
|
||||
Основной сервис для рассылок (`src/core/broadcast_services.py`):
|
||||
|
||||
**Методы:**
|
||||
- `broadcast_to_users()` - рассылка в ЛС
|
||||
- `broadcast_to_channel()` - отправка в канал/группу
|
||||
- `send_message_to_user()` - отправка одному пользователю с обработкой ошибок
|
||||
- `check_user_blocked()` - проверка блокировки
|
||||
- `mark_user_blocked()` - отметить как заблокированного
|
||||
- `unblock_user()` - разблокировать
|
||||
|
||||
#### RedisQueue
|
||||
Класс для работы с Redis очередями:
|
||||
|
||||
**Методы:**
|
||||
- `connect()` - подключение к Redis
|
||||
- `disconnect()` - отключение
|
||||
- `add_to_queue()` - добавить в очередь
|
||||
- `get_from_queue()` - получить из очереди (блокирующая)
|
||||
- `get_queue_length()` - получить длину очереди
|
||||
- `clear_queue()` - очистить очередь
|
||||
|
||||
## Использование
|
||||
|
||||
### Добавление канала/группы
|
||||
|
||||
1. Перейдите в админ-панель → Массовая рассылка → Управление каналами
|
||||
2. Нажмите "Добавить канал/группу"
|
||||
3. Получите ID канала:
|
||||
- Добавьте бота в канал/группу как администратора
|
||||
- Перешлите сообщение из канала боту @userinfobot
|
||||
- Скопируйте ID чата (обычно отрицательное число)
|
||||
4. Отправьте ID боту
|
||||
5. При успешной проверке отправьте описание или /skip
|
||||
|
||||
### Создание рассылки
|
||||
|
||||
1. Перейдите в админ-панель → Массовая рассылка → Создать рассылку
|
||||
2. Выберите тип рассылки:
|
||||
- **ЛС пользователям** - всем зарегистрированным
|
||||
- **В канал** - выберите канал из списка
|
||||
- **В группу** - выберите группу из списка
|
||||
3. Отправьте сообщение (текст, фото, видео или документ)
|
||||
4. Дождитесь завершения и получите статистику
|
||||
|
||||
### Просмотр статистики
|
||||
|
||||
Перейдите в админ-панель → Массовая рассылка → Статистика:
|
||||
- Общее количество рассылок
|
||||
- Количество заблокированных пользователей
|
||||
- История последних 5 рассылок с детальной статистикой
|
||||
|
||||
## Обработка ошибок
|
||||
|
||||
Система автоматически обрабатывает следующие типы ошибок:
|
||||
|
||||
### TelegramForbiddenError
|
||||
Пользователь заблокировал бота. Помечается как `blocked_bot`.
|
||||
|
||||
### TelegramBadRequest
|
||||
- `user is deactivated` → `deactivated`
|
||||
- `user not found` → `not_found`
|
||||
- `chat not found` → `chat_not_found`
|
||||
- Остальные → `bad_request`
|
||||
|
||||
### TelegramRetryAfter (FloodWait)
|
||||
Автоматическая задержка и повторная попытка отправки.
|
||||
|
||||
### Другие ошибки
|
||||
Логируются как `unknown_error`.
|
||||
|
||||
## Конфигурация
|
||||
|
||||
### Переменные окружения
|
||||
|
||||
```env
|
||||
# Redis
|
||||
REDIS_URL=redis://localhost:6379/0 # По умолчанию
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
Redis автоматически запускается при использовании docker-compose:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: lottery_redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- lottery_network
|
||||
```
|
||||
|
||||
### Настройки в коде
|
||||
|
||||
В `BroadcastService` (`src/core/broadcast_services.py`):
|
||||
|
||||
```python
|
||||
BATCH_SIZE = 30 # Сообщений в пакете
|
||||
BATCH_DELAY = 1.0 # Задержка между пакетами (секунды)
|
||||
RETRY_AFTER_DELAY = 5.0 # Дополнительная задержка при FloodWait
|
||||
```
|
||||
|
||||
## Миграция базы данных
|
||||
|
||||
Для применения новых таблиц:
|
||||
|
||||
```bash
|
||||
# Применить миграцию
|
||||
python -m alembic upgrade head
|
||||
|
||||
# Откатить миграцию
|
||||
python -m alembic downgrade -1
|
||||
```
|
||||
|
||||
## Мониторинг
|
||||
|
||||
### Логи
|
||||
|
||||
Все операции рассылки логируются:
|
||||
- Успешные отправки (уровень DEBUG)
|
||||
- Блокировки пользователей (уровень INFO)
|
||||
- FloodWait задержки (уровень WARNING)
|
||||
- Ошибки отправки (уровень ERROR)
|
||||
|
||||
### База данных
|
||||
|
||||
Проверка статистики через SQL:
|
||||
|
||||
```sql
|
||||
-- Количество заблокированных пользователей
|
||||
SELECT COUNT(*) FROM blocked_users WHERE is_active = true;
|
||||
|
||||
-- Статистика рассылок
|
||||
SELECT
|
||||
broadcast_type,
|
||||
COUNT(*) as total,
|
||||
SUM(success_count) as delivered,
|
||||
SUM(blocked_count) as blocked
|
||||
FROM broadcast_logs
|
||||
GROUP BY broadcast_type;
|
||||
```
|
||||
|
||||
## Рекомендации
|
||||
|
||||
1. **Перед запуском большой рассылки:**
|
||||
- Проверьте количество заблокированных пользователей
|
||||
- Убедитесь, что Redis работает
|
||||
- Проверьте логи на наличие ошибок
|
||||
|
||||
2. **При добавлении канала:**
|
||||
- Убедитесь, что бот добавлен как администратор
|
||||
- Проверьте, что бот имеет права на отправку сообщений
|
||||
|
||||
3. **Мониторинг производительности:**
|
||||
- Следите за временем выполнения рассылок
|
||||
- При необходимости увеличьте BATCH_SIZE (не более 40)
|
||||
- Уменьшите BATCH_DELAY при стабильной работе (не менее 0.5 сек)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Проблема: Рассылка зависает
|
||||
|
||||
**Решение:**
|
||||
1. Проверьте подключение к Redis
|
||||
2. Проверьте логи на наличие ошибок
|
||||
3. Убедитесь, что нет FloodWait ошибок
|
||||
|
||||
### Проблема: Не удается добавить канал
|
||||
|
||||
**Решение:**
|
||||
1. Убедитесь, что бот добавлен в канал/группу
|
||||
2. Проверьте права бота (должен быть администратором)
|
||||
3. Убедитесь, что ID правильный (должен быть отрицательным)
|
||||
|
||||
### Проблема: Высокий процент неудач при рассылке
|
||||
|
||||
**Решение:**
|
||||
1. Проверьте количество заблокированных пользователей в статистике
|
||||
2. Увеличьте BATCH_DELAY для снижения нагрузки
|
||||
3. Проверьте логи на частые FloodWait ошибки
|
||||
|
||||
## Безопасность
|
||||
|
||||
- Все операции рассылки доступны только администраторам
|
||||
- ID каналов/групп хранятся в зашифрованном виде (BigInteger)
|
||||
- История рассылок связана с администратором, который ее запустил
|
||||
- Автоматическое логирование всех операций
|
||||
|
||||
## Производительность
|
||||
|
||||
- Redis очереди обеспечивают асинхронную обработку
|
||||
- Пакетная отправка снижает нагрузку на API Telegram
|
||||
- Автоматическое управление задержками предотвращает FloodWait
|
||||
- Кэширование заблокированных пользователей ускоряет рассылку
|
||||
Reference in New Issue
Block a user