- Fixed get_all_active_users() to broadcast to ALL users regardless of registration status - Merged duplicate text message handlers (check_exit_keywords and handle_text_message) - Added detailed logging for chat message broadcasting - Now users can receive messages in chat without full registration Resolves: Messages not being delivered to unregistered users in chat
7.3 KiB
Исправление функции чата
🔴 Проблема
При переходе в чат, сообщения не отправлялись другим участникам. Пользователи не получали сообщения друг от друга.
🔍 Корневые причины (найдено ДВЕ)
Причина 1: Неправильная фильтрация активных пользователей
В функции get_all_active_users() (строка 189-192) рассылка осуществлялась только:
- Зарегистрированным пользователям (
u.is_registered == True) - ИЛИ админам
Это означало, что обычные пользователи, не прошедшие полную регистрацию, не получали сообщения в чате.
Статус в БД: Было 7 пользователей, из них только 2 зарегистрированы, остальные 5 не получали сообщения.
Причина 2: Дублирующиеся обработчики текстовых сообщений
В файле src/handlers/chat_handlers.py было ДВА обработчика для текстовых сообщений в состоянии ChatStates.in_chat:
-
check_exit_keywords()(строка 140):- Декоратор:
@router.message(StateFilter(ChatStates.in_chat), F.text) - Функция: проверяла ключевые слова для выхода (
/start,start,старт,/exit) - ПРОБЛЕМА: если сообщение не было ключевым словом, функция просто заканчивалась без
return, но это НЕ означало, что выполнение продолжится в следующем обработчике. Aiogram использует первый подходящий обработчик, и второй никогда не вызывался.
- Декоратор:
-
handle_text_message()(строка 663) - дублирующий обработчик:- Декоратор:
@router.message(F.text, StateFilter(ChatStates.in_chat)) - Функция: содержала вся логика для рассылки сообщений
- ПРОБЛЕМА: эта функция НИКОГДА не вызывалась, потому что первый обработчик
check_exit_keywords()перехватывал все текстовые сообщения.
- Декоратор:
✅ Сделанные исправления
Исправление 1: Изменена логика получения активных пользователей
# ДО (неправильно):
async def get_all_active_users(session: AsyncSession) -> List:
"""Получить всех пользователей для рассылки (зарегистрированные + админы)"""
users = await UserService.get_all_users(session)
return [u for u in users if u.is_registered or u.telegram_id in ADMIN_IDS]
# ПОСЛЕ (правильно):
async def get_all_active_users(session: AsyncSession) -> List:
"""Получить всех пользователей для рассылки (всем, кто когда-либо общался с ботом)"""
users = await UserService.get_all_users(session)
return users
Исправление 2: Объединены дублирующиеся обработчики
- Объединена вся логика обработки сообщений в
check_exit_keywords()(теперь переименована концептуально, но осталась в коде) - Удален дублирующий обработчик
handle_text_message() - Новая логика:
- Проверяются ключевые слова для выхода (
/start,start,старт,/exit) - Если это не ключевое слово → продолжается обработка как обычного сообщения чата
- Выполняется полная логика рассылки/пересылки
- Проверяются ключевые слова для выхода (
Исправление 3: Добавлено логирование для отладки
Добавлены логи в broadcast_message_with_scheduler():
logger.info(f"[CHAT] broadcast_message_with_scheduler: всего пользователей для рассылки: {len(users)}")
logger.info(f"[CHAT] После исключения отправителя: {len(users)} пользователей")
logger.info(f"[CHAT] broadcast_message_with_scheduler завершена: успешно={success_count}, ошибок={fail_count}")
📊 Измененные файлы
- src/handlers/chat_handlers.py:
- Строка 189-192: Функция
get_all_active_users()теперь возвращает всех пользователей - Строка 140-358: Объединена вся логика обработки текстовых сообщений в функцию
check_exit_keywords() - Строка 663-857: Удален дублирующий обработчик
handle_text_message()
- Строка 189-192: Функция
🧪 Тестирование
Инструкции для тестирования:
- Убедитесь, что есть минимум 2 пользователя в системе (заказывали с 7 пользователями)
- Первый пользователь: отправляет
/chatили нажимает "Войти в чат" - Второй пользователь: отправляет
/chatили нажимает "Войти в чат" - Первый пользователь: отправляет текстовое сообщение в чат
- Второй пользователь: должен получить сообщение с заголовком типа:
- Для админов:
📨 Сообщение от [nickname] (карта: XXXX): - Для обычных пользователей:
📨 [nickname]:
- Для админов:
Проверка логов:
docker compose logs -f bot | grep "\[CHAT\]"
Должны быть строки:
[CHAT] check_exit_keywords вызван для обработки: user=...[CHAT] broadcast_message_with_scheduler: всего пользователей для рассылки: N[CHAT] После исключения отправителя: N пользователей[CHAT] broadcast_message_with_scheduler завершена: успешно=N, ошибок=M
🎯 Ожидаемый результат
После применения этого исправления: ✅ Все пользователи будут получать сообщения в чате ✅ Сообщения будут рассылаться независимо от статуса регистрации ✅ Логирование позволит отследить проблемы при возникновении ✅ Система корректно проверяет ключевые слова для выхода из чата ✅ Сообщения рассылаются всем пользователям, включая незарегистрированных