from telegram import Update from telegram.ext import ContextTypes from app.database import AsyncSessionLocal from app.database.repository import GroupRepository, MessageRepository, MessageGroupRepository from app.utils.keyboards import get_back_keyboard, CallbackType from app.utils import can_send_message from datetime import datetime, timedelta import logging import asyncio logger = logging.getLogger(__name__) async def send_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Отправить сообщение в группы с учетом slow mode""" query = update.callback_query # Парсим callback: send_msg_ callback_data = query.data if callback_data.startswith("send_msg_"): message_id = int(callback_data.split("_")[2]) else: await query.answer("❌ Ошибка обработки", show_alert=True) return async with AsyncSessionLocal() as session: msg_repo = MessageRepository(session) group_repo = GroupRepository(session) mg_repo = MessageGroupRepository(session) message = await msg_repo.get_message(message_id) if not message: await query.answer("❌ Сообщение не найдено", show_alert=True) return # Получить группы, куда нужно отправить message_groups = await mg_repo.get_message_groups_to_send(message_id) if not message_groups: await query.answer("✅ Сообщение уже отправлено во все группы", show_alert=True) return await query.answer() await query.edit_message_text( f"📤 Начинаю отправку '{message.title}' в {len(message_groups)} групп(ы)...\n\n" "⏳ Это может занять некоторое время в зависимости от slow mode." ) # Отправляем в каждую группу sent_count = 0 failed_count = 0 total_wait = 0 for mg in message_groups: try: # Проверяем slow mode can_send, wait_time = await can_send_message(mg.group) if not can_send: # Ждем await query.edit_message_text( f"📤 Отправка '{message.title}'...\n\n" f"✅ Отправлено: {sent_count}\n" f"❌ Ошибок: {failed_count}\n" f"⏳ Ожидание {wait_time}s перед отправкой в {mg.group.title}..." ) await asyncio.sleep(wait_time) total_wait += wait_time # Отправляем сообщение await context.bot.send_message( chat_id=mg.group.chat_id, text=message.text, parse_mode=message.parse_mode ) # Отмечаем как отправленное async with AsyncSessionLocal() as session: mg_repo = MessageGroupRepository(session) await mg_repo.mark_as_sent(mg.id) group_repo = GroupRepository(session) await group_repo.update_last_message_time(mg.group.id) sent_count += 1 except Exception as e: logger.error(f"Ошибка при отправке в группу {mg.group.chat_id}: {e}") async with AsyncSessionLocal() as session: mg_repo = MessageGroupRepository(session) await mg_repo.mark_as_sent(mg.id, error=str(e)) failed_count += 1 # Обновляем сообщение каждые 5 отправок if sent_count % 5 == 0: await query.edit_message_text( f"📤 Отправка '{message.title}'...\n\n" f"✅ Отправлено: {sent_count}\n" f"❌ Ошибок: {failed_count}" ) # Финальное сообщение final_text = f"✅ Отправка завершена\n\n" final_text += f"✅ Успешно: {sent_count}\n" final_text += f"❌ Ошибок: {failed_count}\n" if total_wait > 0: final_text += f"⏳ Всего ожидалось: {total_wait}s" await query.edit_message_text( final_text, parse_mode='HTML', reply_markup=get_back_keyboard() ) async def discover_groups(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """ Обнаружить все группы, в которых есть бот Этот метод вызывается при запуске или по команде """ # Получить список всех чатов, в которых есть бот # NOTE: python-telegram-bot не имеет встроенного способа получить все чаты # Это нужно реализовать через webhook или polling с сохранением информации о новых группах logger.info("Функция обнаружения групп - необходимо добавить обработчик my_chat_member")