""" Обработчик команд для управления расписанием рассылок """ import logging from telegram import Update from telegram.ext import ContextTypes from app.scheduler import broadcast_scheduler, schedule_broadcast, cancel_broadcast, list_broadcasts from app.database.repository import MessageRepository from app.database import AsyncSessionLocal logger = logging.getLogger(__name__) async def schedule_command(update: Update, context: ContextTypes.DEFAULT_TYPE): """Команда для управления расписанием""" if not update.message: return user_id = update.message.from_user.id # Только администратор может управлять расписанием # (это нужно добавить в конфигурацию) try: # /schedule list - показать все расписания if context.args and context.args[0] == 'list': schedules = await list_broadcasts() if not schedules: await update.message.reply_text("📋 Нет активных расписаний") return text = "📅 Активные расписания:\n\n" for idx, sched in enumerate(schedules, 1): text += f"{idx}. {sched['name']}\n" text += f" ID: `{sched['id']}`\n" text += f" Расписание: {sched['trigger']}\n" text += f" Следующее выполнение: {sched['next_run_time']}\n\n" await update.message.reply_text(text, parse_mode='Markdown') # /schedule add message_id group_id cron_expr elif context.args and context.args[0] == 'add': if len(context.args) < 4: await update.message.reply_text( "❌ Использование: /schedule add \n\n" "Пример: /schedule add 1 10 '0 9 * * *'\n\n" "Cron формат: minute hour day month day_of_week\n" "0 9 * * * - ежедневно в 9:00 UTC" ) return try: message_id = int(context.args[1]) group_id = int(context.args[2]) cron_expr = ' '.join(context.args[3:]) # Проверить, что сообщение существует async with AsyncSessionLocal() as session: message_repo = MessageRepository(session) message = await message_repo.get_by_id(message_id) if not message: await update.message.reply_text(f"❌ Сообщение с ID {message_id} не найдено") return job_id = await schedule_broadcast( message_id=message_id, group_ids=[group_id], cron_expr=cron_expr ) await update.message.reply_text( f"✅ Расписание создано!\n\n" f"ID: `{job_id}`\n" f"Сообщение: {message_id}\n" f"Группа: {group_id}\n" f"Расписание: {cron_expr}" ) except ValueError as e: await update.message.reply_text(f"❌ Ошибка: {e}") except Exception as e: logger.error(f"Ошибка при создании расписания: {e}") await update.message.reply_text(f"❌ Ошибка: {e}") # /schedule remove job_id elif context.args and context.args[0] == 'remove': if len(context.args) < 2: await update.message.reply_text( "❌ Использование: /schedule remove " ) return job_id = context.args[1] success = await cancel_broadcast(job_id) if success: await update.message.reply_text(f"✅ Расписание удалено: {job_id}") else: await update.message.reply_text(f"❌ Расписание не найдено: {job_id}") else: await update.message.reply_text( "📅 Управление расписанием\n\n" "Команды:\n" "/schedule list - показать все расписания\n" "/schedule add - добавить расписание\n" "/schedule remove - удалить расписание\n\n" "Примеры cron:\n" "0 9 * * * - ежедневно в 9:00 UTC\n" "0 9 * * MON - по понедельникам в 9:00\n" "*/30 * * * * - каждые 30 минут" ) except Exception as e: logger.error(f"Ошибка в команде schedule: {e}") await update.message.reply_text(f"❌ Ошибка: {e}") async def initialize_scheduler(context: ContextTypes.DEFAULT_TYPE): """Инициализировать планировщик при запуске бота""" try: await broadcast_scheduler.initialize() broadcast_scheduler.start() await broadcast_scheduler.add_maintenance_schedules() logger.info("✅ Планировщик инициализирован и запущен") except Exception as e: logger.error(f"❌ Ошибка при инициализации планировщика: {e}") async def shutdown_scheduler(context: ContextTypes.DEFAULT_TYPE): """Завершить планировщик при остановке бота""" try: await broadcast_scheduler.shutdown() logger.info("✅ Планировщик завершен") except Exception as e: logger.error(f"❌ Ошибка при завершении планировщика: {e}")