fix: исправлена обработка редактирования розыгрышей
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
- Добавлен обработчик handle_edit_field для admin_edit_field_{id}_{field} callbacks
- Исправлен toggle_lottery_active - теперь передаёт state вместо None
- Правильный парсинг lottery_id из позиции 3, а не с конца строки
- Обработка 'message is not modified' в bot_controller
- Модифицированы обработчики сообщений для поддержки редактирования
- Добавлен метод update_lottery в LotteryService
- Исправлены ошибки ValueError и AttributeError в меню редактирования
This commit is contained in:
1
Makefile
1
Makefile
@@ -138,7 +138,6 @@ clear-db:
|
||||
else \
|
||||
echo "❌ Отменено"; \
|
||||
fi
|
||||
|
||||
# Очистка
|
||||
clean:
|
||||
@echo "🧹 Очистка временных файлов..."
|
||||
|
||||
@@ -87,8 +87,21 @@ class BotController(IBotController):
|
||||
is_registered=user.is_registered
|
||||
)
|
||||
|
||||
await callback.message.edit_text(
|
||||
text,
|
||||
reply_markup=keyboard,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
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"
|
||||
)
|
||||
@@ -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]:
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user