diff --git a/src/quizzi/application/bot/handlers.py b/src/quizzi/application/bot/handlers.py index 59344ed..4dbff34 100644 --- a/src/quizzi/application/bot/handlers.py +++ b/src/quizzi/application/bot/handlers.py @@ -32,8 +32,9 @@ async def ensure_user_registered( existing_user = await user_dao.get_by_id(message.from_user.id) groups = await group_dao.get_all() + has_groups = len(groups) > 0 - start_data = {"user_id": message.from_user.id} + start_data = {"user_id": message.from_user.id, "has_groups": has_groups} if pending_test_id: start_data["pending_test_id"] = pending_test_id @@ -44,28 +45,30 @@ async def ensure_user_registered( username=message.from_user.username, last_name=message.from_user.last_name, ) - if len(groups) > 0: - await dialog_manager.start( - UserRegistrationSG.input_name, - mode=StartMode.RESET_STACK, - data=start_data - ) - return False - return True + await dialog_manager.start( + UserRegistrationSG.input_name, + mode=StartMode.RESET_STACK, + data=start_data + ) + return False - if len(groups) > 0 and (existing_user.name is None or existing_user.group is None): - if existing_user.name is None: - await dialog_manager.start( - UserRegistrationSG.input_name, - mode=StartMode.RESET_STACK, - data=start_data - ) - else: - await dialog_manager.start( - UserRegistrationSG.select_group, - mode=StartMode.RESET_STACK, - data=start_data - ) + needs_name = existing_user.name is None + needs_group = has_groups and existing_user.group is None + + if needs_name: + await dialog_manager.start( + UserRegistrationSG.input_name, + mode=StartMode.RESET_STACK, + data=start_data + ) + return False + + if needs_group: + await dialog_manager.start( + UserRegistrationSG.select_group, + mode=StartMode.RESET_STACK, + data=start_data + ) return False await user_dao.upsert( diff --git a/src/quizzi/application/bot/shared_dialogs/templates.py b/src/quizzi/application/bot/shared_dialogs/templates.py index 0f4699e..83f8754 100644 --- a/src/quizzi/application/bot/shared_dialogs/templates.py +++ b/src/quizzi/application/bot/shared_dialogs/templates.py @@ -22,13 +22,18 @@ from quizzi.infrastructure.database.repo.test import TestRepository TEMPLATES_INFO = ( "📦 Шаблоны тестов\n\n" - "Шаблоны позволяют экспортировать и импортировать тесты в формате JSON.\n\n" - "🔹 Экспорт — сохраните тест как файл для резервной копии или передачи\n" - "🔹 Импорт — загрузите тест из файла\n" - "🔹 Спецификация — описание формата JSON для создания тестов вручную" + "Экспорт и импорт тестов в формате JSON\n\n" + "
" + "📤 Экспорт\n" + "Сохранение теста в файл для резервной копии или передачи\n\n" + "📥 Импорт\n" + "Загрузка теста из JSON файла\n\n" + "📋 Спецификация\n" + "Описание формата теста для ручного создания" + "
" ) -SPEC_INFO = """📋 Спецификация формата JSON +SPEC_INFO = """📋 Спецификация формата теста в JSON Структура файла: { diff --git a/src/quizzi/application/bot/user_dialogs/deeplink.py b/src/quizzi/application/bot/user_dialogs/deeplink.py index 93f9ae4..66dd043 100644 --- a/src/quizzi/application/bot/user_dialogs/deeplink.py +++ b/src/quizzi/application/bot/user_dialogs/deeplink.py @@ -12,7 +12,7 @@ from quizzi.infrastructure.database.models import QuestionType from quizzi.infrastructure.database.repo.test import TestRepository from quizzi.infrastructure.database.repo.test_attempt import TestAttemptRepository from quizzi.infrastructure.utils.rate_limiter import PasswordRateLimiter -from quizzi.infrastructure.utils.timezone import now_msk_naive +from quizzi.infrastructure.utils.timezone import now_msk_naive, to_msk @inject @@ -20,12 +20,15 @@ async def get_deeplink_test_data( dialog_manager: DialogManager, test_dao: FromDishka[TestDAO], test_repo: FromDishka[TestRepository], + attempt_repo: FromDishka[TestAttemptRepository], **_kwargs, ): + assert dialog_manager.event.from_user is not None start_data = dialog_manager.start_data or {} assert isinstance(start_data, dict) test_id = start_data.get("test_id") error = start_data.get("error") + user_id = dialog_manager.event.from_user.id if error: return {"test_info": error, "can_start": False} @@ -40,17 +43,26 @@ async def get_deeplink_test_data( questions_count = await test_repo.count_questions_in_test(test_id) + attempts = await attempt_repo.get_user_test_attempts(user_id, test_id) + finished_attempts = [a for a in attempts if a.finished_at] + password_str = "🔒 Требуется пароль" if test.password else "🔓 Без пароля" - attempts_str = f"🔄 Попыток: {test.attempts}" if test.attempts else "🔄 Попыток: ♾️" + attempts_str = f"🔄 Попыток: {len(finished_attempts)}/{test.attempts}" if test.attempts else f"🔄 Попыток: {len(finished_attempts)}/♾️" time_limit_str = f"⏱️ Время: {test.time_limit // 60} мин" if test.time_limit else "⏱️ Без лимита" + expires_at_msk = to_msk(test.expires_at) + expires_str = f"📅 До {expires_at_msk.strftime('%d.%m.%Y %H:%M')}" if expires_at_msk else "📅 Без срока" + group_str = f"🎓 Для группы {test.for_group}" if test.for_group else "👥 Для всех" + test_info = ( f"📝 {test.title}\n\n" f"
{test.description or '—'}
\n\n" f"Вопросов: {questions_count}\n" f"{password_str}\n" f"{attempts_str}\n" - f"{time_limit_str}" + f"{time_limit_str}\n" + f"{expires_str}\n" + f"{group_str}" ) return {"test_info": test_info, "can_start": True, "has_password": bool(test.password)} diff --git a/src/quizzi/application/bot/user_dialogs/main_menu.py b/src/quizzi/application/bot/user_dialogs/main_menu.py index 5bc8895..6b04c1c 100644 --- a/src/quizzi/application/bot/user_dialogs/main_menu.py +++ b/src/quizzi/application/bot/user_dialogs/main_menu.py @@ -436,7 +436,7 @@ user_menu_dialog = Dialog( getter=get_test_detail, ), Window( - Const("✏️ Изменение имени\n\nВведите новое имя:"), + Const("✏️ Изменение имени\n\nВведите имя и фамилию:"), MessageInput(on_name_input), Button(Const("◀️ Назад"), id="back", on_click=on_back_to_main), state=UserMenuSG.edit_name, diff --git a/src/quizzi/application/bot/user_dialogs/registration.py b/src/quizzi/application/bot/user_dialogs/registration.py index 6e12ed1..8b5407a 100644 --- a/src/quizzi/application/bot/user_dialogs/registration.py +++ b/src/quizzi/application/bot/user_dialogs/registration.py @@ -9,6 +9,7 @@ from dishka.integrations.aiogram_dialog import inject from quizzi.application.bot.user_dialogs.states import UserDeeplinkSG, UserMenuSG, UserRegistrationSG from quizzi.infrastructure.database.dao.group import GroupDAO from quizzi.infrastructure.database.dao.user import UserDAO +from quizzi.infrastructure.utils.timezone import now_msk_naive @inject @@ -35,11 +36,24 @@ async def on_name_input( start_data = manager.start_data or {} assert isinstance(start_data, dict) user_id = start_data.get("user_id") + has_groups = start_data.get("has_groups", True) + pending_test_id = start_data.get("pending_test_id") + if user_id: - await user_dao.update(user_id=user_id, name=name) + await user_dao.update(user_id=user_id, name=name, name_updated_at=now_msk_naive()) manager.dialog_data["name"] = name - await manager.switch_to(UserRegistrationSG.select_group) + + if has_groups: + await manager.switch_to(UserRegistrationSG.select_group) + elif pending_test_id: + await manager.start( + UserDeeplinkSG.test_preview, + mode=StartMode.RESET_STACK, + data={"test_id": pending_test_id} + ) + else: + await manager.start(UserMenuSG.main, mode=StartMode.RESET_STACK) @inject @@ -66,7 +80,7 @@ async def on_group_selected( pending_test_id = start_data.get("pending_test_id") if user_id: - await user_dao.update(user_id=user_id, group=int(item_id)) + await user_dao.update(user_id=user_id, group=int(item_id), group_updated_at=now_msk_naive()) if pending_test_id: await manager.start(