Рефакторинг архитектуры ежедневных конкурсов:
- Создан модуль app/services/contests/ с новой архитектурой:
- enums.py: GameType, RoundStatus, PrizeType enum классы
- games.py: паттерн Стратегия для 7 типов игр
- attempt_service.py: ContestAttemptService для атомарных операций
- Упрощён handlers/contests.py:
- Удалены отдельные _render_* функции (заменены на стратегии)
- Логика обработки попыток вынесена в ContestAttemptService
- Уменьшено с 523 до 342 строк (-35%)
- Обновлён contest_rotation_service.py:
- Заменена if-elif цепочка на get_game_strategy().build_payload()
- Используются enum классы вместо магических строк
- Исправлен handlers/admin/daily_contests.py:
- prize_days → prize_type/prize_value (соответствие модели БД)
- Обновлены EDITABLE_FIELDS и отображение приза
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Создание попытки сразу при показе вопроса (cipher/emoji/anagram)
- Проверка attempt.answer is not None для блокировки повторного ответа
- Обновление существующей попытки вместо создания новой
- Добавлена функция update_attempt() в CRUD
Изменения:
- ContestTemplate: prize_days заменен на prize_type и prize_value для поддержки разных типов наград (days, balance, custom)
- _award_prize: обновлена логика выдачи призов для всех типов наград
- DEFAULT_TEMPLATES: обновлены для использования prize_type/prize_value
- upsert_template: обновлена сигнатура для новых полей
- _announce_round_start: добавлена локализация и напоминания о конкурсах
- handle_text_answer: исправлена гонка условий с атомарным инкрементом победителей
- Локализация: добавлены ключи CONTEST_START_ANNOUNCEMENT, CONTEST_PRIZE, DAYS, CONTEST_WINNERS, CONTEST_ATTEMPTS, CONTEST_ELIGIBILITY, REMINDER, CONTEST_REMINDER_TEXT в ru.json и en.json
- API схемы: обновлены ContestTemplateResponse и ContestTemplateUpdateRequest
Требуется миграция БД для новых колонок prize_type и prize_value.
- Добавлена защита от спама: rate limiting для попыток (1 попытка/3-5 сек)
- Усилена валидация входных данных: функция _validate_callback_data для безопасного парсинга callback.data
- Перепроверка авторизации: статус подписки проверяется на каждом шаге
- Атомарные операции победителей: использование select with_for_update для предотвращения гонок условий
- Улучшено логирование: добавлены логи попыток и побед для аудита
- Добавлена кнопка 'Назад' в игру 'Блиц' для предотвращения застревания пользователей
- Исправлены отступы и ошибки линтера в _render_blitz
Все изменения направлены на повышение безопасности, стабильности и UX конкурсов.