271 lines
11 KiB
Markdown
271 lines
11 KiB
Markdown
# Система рассылок с 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
|
||
- Кэширование заблокированных пользователей ускоряет рассылку
|