# Настройка планировщика рассылки ## Проблема Telegram имеет лимиты на количество отправляемых сообщений: - **30 сообщений в секунду** для ботов - При превышении возникает ошибка `Too Many Requests` (код 429) - Бот может быть временно заблокирован ## Решение Реализован **планировщик пакетной рассылки** с контролируемой задержкой между пакетами. ### Параметры планировщика ```python # В файле src/handlers/chat_handlers.py BATCH_SIZE = 20 # Количество сообщений в одном пакете BATCH_DELAY = 1.0 # Задержка между пакетами в секундах ``` ### Как это работает 1. **Получение списка пользователей:** - Загружаются все зарегистрированные пользователи (`is_registered=True`) - Исключается отправитель сообщения 2. **Разбиение на пакеты:** - Пользователи разбиваются на группы по `BATCH_SIZE` (по умолчанию 20) - Например, 100 пользователей = 5 пакетов по 20 3. **Параллельная отправка внутри пакета:** - В каждом пакете сообщения отправляются параллельно через `asyncio.gather()` - Это ускоряет доставку без превышения лимитов 4. **Задержка между пакетами:** - После отправки пакета выжидается `BATCH_DELAY` секунд - Это предотвращает превышение лимита 30 сообщений/сек 5. **Обработка ошибок:** - Ошибки отправки отлавливаются для каждого пользователя - Статистика успешных/неуспешных доставок ведется отдельно ### Математика **Скорость отправки:** - Пакет из 20 сообщений отправляется параллельно ≈ за 0.5-1 секунду - Задержка между пакетами: 1 секунда - Итого: **~20 сообщений за 1.5-2 секунды** = **10-13 сообщений/сек** - Это в **2-3 раза меньше** лимита Telegram (30/сек) **Пример для 100 пользователей:** - 5 пакетов по 20 сообщений - Время отправки: 5 × (1 сек отправка + 1 сек задержка) = **10 секунд** - Средняя скорость: 10 сообщений/сек **Пример для 1000 пользователей:** - 50 пакетов по 20 сообщений - Время отправки: 50 × 2 сек = **100 секунд (1.5 минуты)** - Средняя скорость: 10 сообщений/сек ### Настройка параметров #### Увеличение скорости Если нужно быстрее рассылать и у вас стабильное соединение: ```python BATCH_SIZE = 25 # Больше сообщений в пакете BATCH_DELAY = 0.8 # Меньше задержка ``` ⚠️ **Риск:** При > 30 сообщений/сек может быть блокировка #### Уменьшение нагрузки Если возникают ошибки 429 или нестабильное соединение: ```python BATCH_SIZE = 15 # Меньше сообщений в пакете BATCH_DELAY = 1.5 # Больше задержка ``` ✅ **Безопаснее:** Меньше шанс блокировки #### Для VIP ботов (верифицированных) Telegram может повысить лимиты для верифицированных ботов: ```python BATCH_SIZE = 30 # Можно больше BATCH_DELAY = 0.5 # Можно быстрее ``` ## Пример работы ### Код функции ```python async def broadcast_message_with_scheduler(message: Message, exclude_user_id: Optional[int] = None): """Разослать сообщение всем пользователям с планировщиком""" async with async_session_maker() as session: users = await get_all_active_users(session) if exclude_user_id: users = [u for u in users if u.telegram_id != exclude_user_id] forwarded_ids = {} success_count = 0 fail_count = 0 # Разбиваем на пакеты for i in range(0, len(users), BATCH_SIZE): batch = users[i:i + BATCH_SIZE] # Отправляем пакет параллельно tasks = [_send_message_to_user(message, u.telegram_id) for u in batch] results = await asyncio.gather(*tasks, return_exceptions=True) # Подсчитываем статистику for user, result in zip(batch, results): if isinstance(result, Exception): fail_count += 1 elif result is not None: forwarded_ids[str(user.telegram_id)] = result success_count += 1 else: fail_count += 1 # Задержка между пакетами if i + BATCH_SIZE < len(users): await asyncio.sleep(BATCH_DELAY) return forwarded_ids, success_count, fail_count ``` ### Статистика для пользователя После рассылки пользователь видит: ``` ✅ Сообщение разослано! 📤 Доставлено: 95 ❌ Не доставлено: 5 ``` **Причины неуспешной доставки:** - Пользователь заблокировал бота - Пользователь удалил аккаунт - Временные сетевые проблемы - Ограничения Telegram на стороне получателя ## История сообщений Все ID отправленных сообщений сохраняются в БД: ```sql -- Таблица chat_messages forwarded_message_ids JSONB -- Пример данных: { "123456789": 12345, -- telegram_id: message_id "987654321": 12346, "555555555": 12347 } ``` Это позволяет: - Удалять сообщения у всех пользователей через `/delete_msg` - Отслеживать кому было доставлено сообщение - Собирать статистику рассылок ## Рекомендации ### Для маленьких групп (< 50 пользователей) Можно использовать параметры по умолчанию: ```python BATCH_SIZE = 20 BATCH_DELAY = 1.0 ``` ### Для средних групп (50-200 пользователей) Рекомендуется: ```python BATCH_SIZE = 20 BATCH_DELAY = 1.0 ``` Время рассылки: ~20-40 секунд ### Для больших групп (200-1000 пользователей) Рекомендуется: ```python BATCH_SIZE = 25 BATCH_DELAY = 1.0 ``` Время рассылки: ~1.5-3 минуты ### Для очень больших групп (> 1000 пользователей) Рассмотрите: - Увеличение `BATCH_SIZE` до 30 - Использование очередей (RabbitMQ, Celery) - Распределение нагрузки на несколько ботов ## Мониторинг Для отслеживания работы планировщика смотрите логи: ```bash tail -f logs/bot.log | grep "Failed to send" ``` Каждая неуспешная отправка логируется: ``` Failed to send message to 123456789: Forbidden: bot was blocked by the user Failed to send message to 987654321: Bad Request: chat not found ``` ## Тестирование Для тестирования планировщика: 1. Создайте несколько тестовых аккаунтов 2. Отправьте сообщение через бота 3. Проверьте время доставки и статистику 4. Настройте параметры под свою нагрузку ## Troubleshooting ### Ошибка "Too Many Requests" **Симптомы:** Бот периодически выдает ошибку 429 **Решение:** ```python BATCH_SIZE = 15 # Уменьшить размер пакета BATCH_DELAY = 1.5 # Увеличить задержку ``` ### Медленная рассылка **Симптомы:** Рассылка занимает слишком много времени **Решение:** ```python BATCH_SIZE = 25 # Увеличить размер пакета BATCH_DELAY = 0.8 # Уменьшить задержку ``` ⚠️ Следите за ошибками 429! ### Большое количество неуспешных доставок **Причины:** - Пользователи массово блокируют бота - Проблемы с сетью/сервером - Некорректные telegram_id в базе **Решение:** - Регулярно очищайте неактивных пользователей - Мониторьте состояние сервера - Валидируйте данные при регистрации ## Итого ✅ **Защита от блокировки**: Лимит 30 сообщений/сек не превышается ✅ **Гибкость**: Легко настроить под свою нагрузку ✅ **Статистика**: Точный подсчет успешных/неуспешных доставок ✅ **История**: Все ID сохраняются для модерации ✅ **Параллелизм**: Быстрая отправка внутри пакета **Рекомендуемые параметры:** ```python BATCH_SIZE = 20 BATCH_DELAY = 1.0 ``` Это обеспечивает баланс между скоростью и безопасностью.