11 KiB
Система рассылок с Redis очередями
Обзор
Расширенная система массовых рассылок с поддержкой трех типов рассылки:
- ЛС пользователям - массовая рассылка по личным сообщениям с отслеживанием заблокированных
- В канал - отправка в Telegram канал
- В группу - отправка в Telegram группу
Основные возможности
1. Рассылка в личные сообщения
Особенности:
- Использование Redis очередей для управления потоком сообщений
- Автоматическое отслеживание пользователей, заблокировавших бота
- Пакетная отправка с задержками для соблюдения лимитов Telegram
- Детальная обработка ошибок (блокировка, деактивация аккаунта, etc.)
- Автоматическое повторение при FloodWait ошибках
Технические детали:
- Размер пакета: 30 сообщений
- Задержка между пакетами: 1 секунда
- Дополнительная задержка при FloodWait: 5 секунд + время из ошибки
2. Рассылка в канал/группу
Особенности:
- Управление списком каналов и групп через админ-панель
- Проверка прав бота перед добавлением канала
- Возможность добавить описание для каждого канала
- Активация/деактивация каналов
Архитектура
Модели данных
BroadcastChannel
Хранит информацию о каналах и группах для рассылки:
chat_id- ID чата в Telegramchat_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()- подключение к Redisdisconnect()- отключениеadd_to_queue()- добавить в очередьget_from_queue()- получить из очереди (блокирующая)get_queue_length()- получить длину очередиclear_queue()- очистить очередь
Использование
Добавление канала/группы
- Перейдите в админ-панель → Массовая рассылка → Управление каналами
- Нажмите "Добавить канал/группу"
- Получите ID канала:
- Добавьте бота в канал/группу как администратора
- Перешлите сообщение из канала боту @userinfobot
- Скопируйте ID чата (обычно отрицательное число)
- Отправьте ID боту
- При успешной проверке отправьте описание или /skip
Создание рассылки
- Перейдите в админ-панель → Массовая рассылка → Создать рассылку
- Выберите тип рассылки:
- ЛС пользователям - всем зарегистрированным
- В канал - выберите канал из списка
- В группу - выберите группу из списка
- Отправьте сообщение (текст, фото, видео или документ)
- Дождитесь завершения и получите статистику
Просмотр статистики
Перейдите в админ-панель → Массовая рассылка → Статистика:
- Общее количество рассылок
- Количество заблокированных пользователей
- История последних 5 рассылок с детальной статистикой
Обработка ошибок
Система автоматически обрабатывает следующие типы ошибок:
TelegramForbiddenError
Пользователь заблокировал бота. Помечается как blocked_bot.
TelegramBadRequest
user is deactivated→deactivateduser not found→not_foundchat not found→chat_not_found- Остальные →
bad_request
TelegramRetryAfter (FloodWait)
Автоматическая задержка и повторная попытка отправки.
Другие ошибки
Логируются как unknown_error.
Конфигурация
Переменные окружения
# Redis
REDIS_URL=redis://localhost:6379/0 # По умолчанию
Docker Compose
Redis автоматически запускается при использовании docker-compose:
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):
BATCH_SIZE = 30 # Сообщений в пакете
BATCH_DELAY = 1.0 # Задержка между пакетами (секунды)
RETRY_AFTER_DELAY = 5.0 # Дополнительная задержка при FloodWait
Миграция базы данных
Для применения новых таблиц:
# Применить миграцию
python -m alembic upgrade head
# Откатить миграцию
python -m alembic downgrade -1
Мониторинг
Логи
Все операции рассылки логируются:
- Успешные отправки (уровень DEBUG)
- Блокировки пользователей (уровень INFO)
- FloodWait задержки (уровень WARNING)
- Ошибки отправки (уровень ERROR)
База данных
Проверка статистики через 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;
Рекомендации
-
Перед запуском большой рассылки:
- Проверьте количество заблокированных пользователей
- Убедитесь, что Redis работает
- Проверьте логи на наличие ошибок
-
При добавлении канала:
- Убедитесь, что бот добавлен как администратор
- Проверьте, что бот имеет права на отправку сообщений
-
Мониторинг производительности:
- Следите за временем выполнения рассылок
- При необходимости увеличьте BATCH_SIZE (не более 40)
- Уменьшите BATCH_DELAY при стабильной работе (не менее 0.5 сек)
Troubleshooting
Проблема: Рассылка зависает
Решение:
- Проверьте подключение к Redis
- Проверьте логи на наличие ошибок
- Убедитесь, что нет FloodWait ошибок
Проблема: Не удается добавить канал
Решение:
- Убедитесь, что бот добавлен в канал/группу
- Проверьте права бота (должен быть администратором)
- Убедитесь, что ID правильный (должен быть отрицательным)
Проблема: Высокий процент неудач при рассылке
Решение:
- Проверьте количество заблокированных пользователей в статистике
- Увеличьте BATCH_DELAY для снижения нагрузки
- Проверьте логи на частые FloodWait ошибки
Безопасность
- Все операции рассылки доступны только администраторам
- ID каналов/групп хранятся в зашифрованном виде (BigInteger)
- История рассылок связана с администратором, который ее запустил
- Автоматическое логирование всех операций
Производительность
- Redis очереди обеспечивают асинхронную обработку
- Пакетная отправка снижает нагрузку на API Telegram
- Автоматическое управление задержками предотвращает FloodWait
- Кэширование заблокированных пользователей ускоряет рассылку