diff --git a/Makefile b/Makefile index cb72534..7a22b7e 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,6 @@ clear-db: else \ echo "❌ Отменено"; \ fi - # Очистка clean: @echo "🧹 Очистка временных файлов..." diff --git a/src/controllers/bot_controller.py b/src/controllers/bot_controller.py index 3e32575..2aea356 100644 --- a/src/controllers/bot_controller.py +++ b/src/controllers/bot_controller.py @@ -87,8 +87,21 @@ class BotController(IBotController): is_registered=user.is_registered ) - await callback.message.edit_text( - text, - reply_markup=keyboard, - parse_mode="Markdown" - ) \ No newline at end of file + try: + await callback.message.edit_text( + text, + reply_markup=keyboard, + parse_mode="Markdown" + ) + except Exception as e: + # Если сообщение не изменилось - просто отвечаем на callback + if "message is not modified" in str(e): + await callback.answer("✅ Уже показаны активные розыгрыши") + else: + # Другие ошибки - пробуем отправить новое сообщение + await callback.answer() + await callback.message.answer( + text, + reply_markup=keyboard, + parse_mode="Markdown" + ) \ No newline at end of file diff --git a/src/core/services.py b/src/core/services.py index 8b224b0..8b8ed5a 100644 --- a/src/core/services.py +++ b/src/core/services.py @@ -227,6 +227,25 @@ class LotteryService: result = await session.execute(query) return result.scalars().all() + + @staticmethod + async def update_lottery( + session: AsyncSession, + lottery_id: int, + **updates + ) -> bool: + """Обновить данные розыгрыша""" + try: + await session.execute( + update(Lottery) + .where(Lottery.id == lottery_id) + .values(**updates) + ) + await session.commit() + return True + except Exception: + await session.rollback() + return False @staticmethod async def get_all_lotteries(session: AsyncSession, limit: Optional[int] = None) -> List[Lottery]: diff --git a/src/handlers/admin_panel.py b/src/handlers/admin_panel.py index c183229..f5d1eaa 100644 --- a/src/handlers/admin_panel.py +++ b/src/handlers/admin_panel.py @@ -236,11 +236,41 @@ async def start_create_lottery(callback: CallbackQuery, state: FSMContext): @admin_router.message(StateFilter(AdminStates.lottery_title)) async def process_lottery_title(message: Message, state: FSMContext): - """Обработка названия розыгрыша""" + """Обработка названия розыгрыша (создание или редактирование)""" if not is_admin(message.from_user.id): await message.answer("❌ Недостаточно прав") return + data = await state.get_data() + edit_lottery_id = data.get('edit_lottery_id') + + # Если это редактирование существующего розыгрыша + if edit_lottery_id: + async with async_session_maker() as session: + success = await LotteryService.update_lottery( + session, + edit_lottery_id, + title=message.text + ) + + if success: + await message.answer(f"✅ Название изменено на: {message.text}") + await state.clear() + # Возвращаемся к выбору полей + from aiogram.types import CallbackQuery + fake_callback = CallbackQuery( + id="fake", + from_user=message.from_user, + chat_instance="fake", + data=f"admin_edit_lottery_select_{edit_lottery_id}", + message=message + ) + await choose_edit_field(fake_callback, state) + else: + await message.answer("❌ Ошибка при изменении названия") + return + + # Если это создание нового розыгрыша await state.update_data(title=message.text) text = f"📝 Создание нового розыгрыша\n\n" @@ -254,11 +284,42 @@ async def process_lottery_title(message: Message, state: FSMContext): @admin_router.message(StateFilter(AdminStates.lottery_description)) async def process_lottery_description(message: Message, state: FSMContext): - """Обработка описания розыгрыша""" + """Обработка описания розыгрыша (создание или редактирование)""" if not is_admin(message.from_user.id): await message.answer("❌ Недостаточно прав") return + data = await state.get_data() + edit_lottery_id = data.get('edit_lottery_id') + + # Если это редактирование существующего розыгрыша + if edit_lottery_id: + description = None if message.text == "-" else message.text + async with async_session_maker() as session: + success = await LotteryService.update_lottery( + session, + edit_lottery_id, + description=description + ) + + if success: + await message.answer(f"✅ Описание изменено") + await state.clear() + # Возвращаемся к выбору полей + from aiogram.types import CallbackQuery + fake_callback = CallbackQuery( + id="fake", + from_user=message.from_user, + chat_instance="fake", + data=f"admin_edit_lottery_select_{edit_lottery_id}", + message=message + ) + await choose_edit_field(fake_callback, state) + else: + await message.answer("❌ Ошибка при изменении описания") + return + + # Если это создание нового розыгрыша description = None if message.text == "-" else message.text await state.update_data(description=description) @@ -281,12 +342,43 @@ async def process_lottery_description(message: Message, state: FSMContext): @admin_router.message(StateFilter(AdminStates.lottery_prizes)) async def process_lottery_prizes(message: Message, state: FSMContext): - """Обработка призов розыгрыша""" + """Обработка призов розыгрыша (создание или редактирование)""" if not is_admin(message.from_user.id): await message.answer("❌ Недостаточно прав") return + data = await state.get_data() + edit_lottery_id = data.get('edit_lottery_id') + prizes = [prize.strip() for prize in message.text.split('\n') if prize.strip()] + + # Если это редактирование существующего розыгрыша + if edit_lottery_id: + async with async_session_maker() as session: + success = await LotteryService.update_lottery( + session, + edit_lottery_id, + prizes=prizes + ) + + if success: + await message.answer(f"✅ Призы изменены") + await state.clear() + # Возвращаемся к выбору полей + from aiogram.types import CallbackQuery + fake_callback = CallbackQuery( + id="fake", + from_user=message.from_user, + chat_instance="fake", + data=f"admin_edit_lottery_select_{edit_lottery_id}", + message=message + ) + await choose_edit_field(fake_callback, state) + else: + await message.answer("❌ Ошибка при изменении призов") + return + + # Если это создание нового розыгрыша await state.update_data(prizes=prizes) data = await state.get_data() @@ -1775,8 +1867,49 @@ async def choose_edit_field(callback: CallbackQuery, state: FSMContext): await callback.message.edit_text(text, reply_markup=InlineKeyboardMarkup(inline_keyboard=buttons)) +@admin_router.callback_query(F.data.startswith("admin_edit_field_")) +async def handle_edit_field(callback: CallbackQuery, state: FSMContext): + """Обработка выбора поля для редактирования""" + if not is_admin(callback.from_user.id): + await callback.answer("❌ Недостаточно прав", show_alert=True) + return + + # Парсим callback_data: admin_edit_field_{lottery_id}_{field_name} + parts = callback.data.split("_") + if len(parts) < 5: + await callback.answer("❌ Неверный формат данных", show_alert=True) + return + + lottery_id = int(parts[3]) # admin_edit_field_{lottery_id}_... + field_name = "_".join(parts[4:]) # Всё после lottery_id это имя поля + + await state.update_data(edit_lottery_id=lottery_id, edit_field=field_name) + + # Определяем, что редактируем + if field_name == "title": + text = "📝 Введите новое название розыгрыша:" + await state.set_state(AdminStates.lottery_title) + elif field_name == "description": + text = "📄 Введите новое описание розыгрыша:" + await state.set_state(AdminStates.lottery_description) + elif field_name == "prizes": + text = "🎁 Введите новый список призов (каждый приз с новой строки):" + await state.set_state(AdminStates.lottery_prizes) + else: + await callback.answer("❌ Неизвестное поле", show_alert=True) + return + + await callback.message.edit_text( + text, + reply_markup=InlineKeyboardMarkup(inline_keyboard=[ + [InlineKeyboardButton(text="❌ Отмена", callback_data="admin_lotteries")] + ]) + ) + await callback.answer() + + @admin_router.callback_query(F.data.startswith("admin_toggle_active_")) -async def toggle_lottery_active(callback: CallbackQuery): +async def toggle_lottery_active(callback: CallbackQuery, state: FSMContext): """Переключить активность розыгрыша""" if not is_admin(callback.from_user.id): await callback.answer("❌ Недостаточно прав", show_alert=True) @@ -1798,7 +1931,7 @@ async def toggle_lottery_active(callback: CallbackQuery): await callback.answer("❌ Ошибка изменения статуса", show_alert=True) # Обновляем отображение - await choose_edit_field(callback, None) + await choose_edit_field(callback, state) @admin_router.callback_query(F.data == "admin_finish_lottery")