Files
new_lottery_bot/docs/AUTO_CONFIRM_SYSTEM.md
Andrew K. Choi 505d26f0e9
Some checks reported errors
continuous-integration/drone/push Build encountered an error
feat: Система автоматического подтверждения выигрышей с поддержкой множественных счетов
Основные изменения:

 Новые функции:
- Система регистрации пользователей с множественными счетами
- Автоматическое подтверждение выигрышей через inline-кнопки
- Механизм переигровки для неподтвержденных выигрышей (24 часа)
- Подтверждение на уровне счетов (каждый счет подтверждается отдельно)
- Скрипт полной очистки базы данных

🔧 Технические улучшения:
- Исправлена ошибка MissingGreenlet при lazy loading (добавлен joinedload/selectinload)
- Добавлено поле claimed_at для отслеживания времени подтверждения
- Пакетное добавление счетов с выбором розыгрыша
- Проверка владения конкретным счетом при подтверждении

📚 Документация:
- docs/AUTO_CONFIRM_SYSTEM.md - Полная документация системы подтверждения
- docs/ACCOUNT_BASED_CONFIRMATION.md - Подтверждение на уровне счетов
- docs/REGISTRATION_SYSTEM.md - Система регистрации
- docs/ADMIN_COMMANDS.md - Команды администратора
- docs/CLEAR_DATABASE.md - Очистка БД
- docs/QUICK_GUIDE.md - Быстрое начало
- docs/UPDATE_LOG.md - Журнал обновлений

🗄️ База данных:
- Миграция 003: Таблицы accounts, winner_verifications
- Миграция 004: Поле claimed_at в таблице winners
- Скрипт scripts/clear_database.py для полной очистки

🎮 Новые команды:
Админские:
- /check_unclaimed <lottery_id> - Проверка неподтвержденных выигрышей
- /redraw <lottery_id> - Повторный розыгрыш
- /add_accounts - Пакетное добавление счетов
- /list_accounts <telegram_id> - Список счетов пользователя

Пользовательские:
- /register - Регистрация с вводом данных
- /my_account - Просмотр своих счетов
- Callback confirm_win_{id} - Подтверждение выигрыша

🛠️ Makefile:
- make clear-db - Очистка всех данных из БД (с подтверждением)

🔒 Безопасность:
- Проверка владения счетом при подтверждении
- Защита от подтверждения чужих счетов
- Независимое подтверждение каждого выигрышного счета

📊 Логика работы:
1. Пользователь регистрируется и добавляет счета
2. Счета участвуют в розыгрыше
3. Победители получают уведомление с кнопкой подтверждения
4. Каждый счет подтверждается отдельно (24 часа на подтверждение)
5. Неподтвержденные выигрыши переигрываются через /redraw
2025-11-16 14:01:30 +09:00

15 KiB
Raw Permalink Blame History

Система автоматического подтверждения и повторного розыгрыша

🎯 Обзор системы

Реализована полная система автоматического подтверждения выигрышей с возможностью повторного розыгрыша для неподтвержденных призов.


🔄 Как это работает

1. Победитель получает уведомление

После проведения розыгрыша победителю автоматически отправляется сообщение с интерактивной кнопкой:

🎉 Поздравляем! Ваш счет выиграл!

🎯 Розыгрыш: Новогодний розыгрыш
🏆 Место: 1
🎁 Приз: Главный приз
💳 Счет: 11-22-33-44-55-66-77

⏰ У вас есть 24 часа для подтверждения!

Нажмите кнопку ниже, чтобы подтвердить получение приза.
Если вы не подтвердите в течение 24 часов, приз будет разыгран заново.

[✅ Подтвердить получение приза]
[📞 Связаться с администратором]

2. Победитель подтверждает выигрыш

Пользователь нажимает кнопку " Подтвердить получение приза":

Что происходит:

  • В БД устанавливается is_claimed = True
  • Сохраняется время подтверждения claimed_at
  • Победитель видит подтверждение:
✅ Выигрыш успешно подтвержден!

🎯 Розыгрыш: Новогодний розыгрыш
🏆 Место: 1
🎁 Приз: Главный приз

🎊 Поздравляем! Администратор свяжется с вами 
для передачи приза в ближайшее время.

Спасибо за участие!

Администраторы получают уведомление:

✅ Победитель подтвердил получение приза!

🎯 Розыгрыш: Новогодний розыгрыш
🏆 Место: 1
🎁 Приз: Главный приз
👤 Победитель: Иван (@ivan)
🎫 Клубная карта: 2223
📱 Телефон: +7 900 123-45-67
💳 Счет: 11-22-33-44-55-66-77

3. Если победитель не подтверждает (24 часа)

Администратор проверяет неподтвержденные выигрыши:

/check_unclaimed 1

Ответ бота:

⚠️ Неподтвержденные выигрыши в розыгрыше 'Новогодний розыгрыш':

🏆 1 место - Главный приз
   👤 Иван (КК: 2223)
   💳 11-22-33-44-55-66-77
   ⏰ Прошло: 26 часов

🏆 3 место - Третий приз
   👤 Петр (КК: 3334)
   💳 22-33-44-55-66-77-88
   ⏰ Прошло: 30 часов

📊 Всего неподтвержденных: 2

Используйте /redraw 1 для повторного розыгрыша

4. Повторный розыгрыш

Администратор запускает переигровку:

/redraw 1

Что происходит:

  1. Система находит неподтвержденные выигрыши (старше 24 часов)
  2. Получает пул участников (исключая текущих победителей)
  3. Случайно выбирает новых победителей для каждого неподтвержденного места
  4. Удаляет старых победителей из БД
  5. Создает новых победителей
  6. Отправляет уведомления новым победителям (с кнопкой подтверждения)

Результат для администратора:

🔄 Повторный розыгрыш завершен!

🎯 Розыгрыш: Новогодний розыгрыш
📊 Переиграно мест: 2

🏆 1 место - Главный приз
   ❌ Было: 11-22-33-44-55-66-77
   ✅ Стало: 99-88-77-66-55-44-33

🏆 3 место - Третий приз
   ❌ Было: 22-33-44-55-66-77-88
   ✅ Стало: 12-34-56-78-90-12-34

📨 Новым победителям отправлены уведомления

Новые победители получают то же уведомление с кнопкой подтверждения и 24-часовым лимитом.


📋 Админские команды

/check_unclaimed <lottery_id>

Проверить неподтвержденные выигрыши старше 24 часов.

Пример:

/check_unclaimed 1

Показывает:

  • Список всех неподтвержденных выигрышей
  • Информацию о победителях
  • Сколько времени прошло с момента уведомления

/redraw <lottery_id>

Переиграть розыгрыш для неподтвержденных выигрышей.

Пример:

/redraw 1

Требования:

  • Должны быть неподтвержденные выигрыши старше 24 часов
  • Должны быть доступные участники (не победители)

🗄️ Изменения в базе данных

Таблица winners

Добавлено новое поле:

  • claimed_at (TIMESTAMP) - время подтверждения выигрыша победителем

Миграция

Файл: migrations/versions/004_add_claimed_at.py

Применить:

alembic upgrade head

🔧 Технические детали

Обработчик подтверждения

Файл: main.py

Callback: confirm_win_{winner_id}

Функция: confirm_winner_response()

Логика:

  1. Проверяет существование выигрыша
  2. Проверяет, что подтверждает владелец
  3. Устанавливает is_claimed = True и claimed_at = now()
  4. Обновляет сообщение победителя
  5. Уведомляет всех администраторов

Система уведомлений

Функция: notify_winners_async()

Изменения:

  • Добавлена кнопка " Подтвердить получение приза"
  • Добавлено предупреждение о 24-часовом лимите
  • Добавлена кнопка "📞 Связаться с администратором"

Повторный розыгрыш

Файл: src/handlers/redraw_handlers.py

Команды:

  • check_unclaimed_winners() - проверка
  • redraw_lottery() - переигровка

Алгоритм:

  1. Получает всех победителей розыгрыша
  2. Фильтрует неподтвержденных (is_claimed=False, is_notified=True, >24ч)
  3. Получает пул участников (исключая победителей)
  4. Для каждого неподтвержденного:
    • Выбирает случайного участника
    • Удаляет старого победителя
    • Создает нового победителя
    • Отправляет уведомление

📊 Состояния выигрыша

Таймлайн жизни выигрыша:

1. Розыгрыш проведен
   ├─ is_notified: False
   ├─ is_claimed: False
   └─ claimed_at: NULL

2. Уведомление отправлено
   ├─ is_notified: True
   ├─ is_claimed: False
   └─ claimed_at: NULL

3А. Победитель подтвердил (успех)
   ├─ is_notified: True
   ├─ is_claimed: True
   └─ claimed_at: 2025-11-16 13:00:00

3Б. Прошло 24 часа (неудача)
   ├─ is_notified: True
   ├─ is_claimed: False
   ├─ claimed_at: NULL
   └─ ⏰ time_passed > 24h → переигровка

4. После переигровки (новый победитель)
   ├─ Старый победитель удален
   ├─ Создан новый победитель
   ├─ is_notified: True (после отправки)
   ├─ is_claimed: False
   └─ claimed_at: NULL → снова 24 часа

⚠️ Важные моменты

Безопасность

  1. Проверка владельца: Только владелец счета может подтвердить выигрыш
  2. Повторное подтверждение: Если выигрыш уже подтвержден, показывается соответствующее сообщение
  3. Права администратора: Только админы могут запускать /redraw

Ограничения

  1. 24-часовой лимит: Жестко закодирован, но легко изменить в коде
  2. Пул участников: Если все участники уже победители, переигровка невозможна
  3. Уникальность: Один счет не может выиграть дважды в одном розыгрыше

Отказоустойчивость

  1. Уведомления: Если не удается отправить - продолжает работу
  2. Транзакции: Все изменения в БД атомарны
  3. Логирование: Все действия записываются в лог

🎯 Типичные сценарии

Сценарий 1: Все подтвердили

1. Розыгрыш → 3 победителя
2. Все 3 нажали кнопку подтверждения
3. Админ: /check_unclaimed 1
   → "✅ Все победители подтвердили выигрыш"
4. Приз передается всем победителям

Сценарий 2: Один не подтвердил

1. Розыгрыш → 3 победителя
2. 2 подтвердили, 1 игнорирует
3. Через 25 часов админ: /check_unclaimed 1
   → "⚠️ 1 неподтвержденный выигрыш"
4. Админ: /redraw 1
5. Система переигрывает 1 место
6. Новый победитель получает уведомление
7. У нового победителя снова 24 часа

Сценарий 3: Множественная переигровка

1. Розыгрыш → 5 победителей
2. 3 подтвердили, 2 игнорируют
3. Через 25 часов: /redraw 1
4. 2 новых победителя выбраны
5. Один из новых тоже игнорирует
6. Через 25 часов: /redraw 1 снова
7. Выбран еще один новый победитель

📈 Статистика и мониторинг

Проверка статуса

/winner_status 1

Покажет:

  • Подтвержденные выигрыши (с is_claimed=True)
  • Ожидающие подтверждения (с is_claimed=False)
  • 📨 Статус уведомления (is_notified)

SQL запросы для админа

Найти все неподтвержденные старше 24 часов:

SELECT w.*, l.title 
FROM winners w
JOIN lotteries l ON w.lottery_id = l.id
WHERE w.is_notified = TRUE 
  AND w.is_claimed = FALSE
  AND w.created_at < NOW() - INTERVAL '24 hours';

Статистика по подтверждениям:

SELECT 
    lottery_id,
    COUNT(*) as total_winners,
    SUM(CASE WHEN is_claimed THEN 1 ELSE 0 END) as confirmed,
    SUM(CASE WHEN NOT is_claimed THEN 1 ELSE 0 END) as unconfirmed
FROM winners
WHERE is_notified = TRUE
GROUP BY lottery_id;

🚀 Использование

Для администратора

  1. После розыгрыша: Ничего не делать - система отправит уведомления
  2. Через 24-30 часов: Проверить /check_unclaimed <id>
  3. Если есть неподтвержденные: Запустить /redraw <id>
  4. Повторить при необходимости

Для победителя

  1. Получить уведомление с кнопкой
  2. Нажать " Подтвердить"
  3. Дождаться связи с админом
  4. Получить приз

💡 Рекомендации

Оптимальные настройки

  • Лимит подтверждения: 24 часа (можно увеличить до 48ч)
  • Частота проверки: 1-2 раза в день
  • Уведомления: Включить push-уведомления в боте

Коммуникация с пользователями

После розыгрыша отправьте общее сообщение:

🎉 Розыгрыш завершен!

Если вы выиграли, вам придет сообщение с кнопкой подтверждения.

⏰ У вас будет 24 часа чтобы подтвердить выигрыш!

Если не подтвердите - приз будет переигран.

🔮 Возможные улучшения

  1. Напоминания: Отправка напоминания за 2 часа до истечения срока
  2. Гибкий лимит: Разные лимиты для разных типов призов
  3. История: Логирование всех переигровок
  4. Статистика: Процент подтверждений, среднее время подтверждения
  5. Автоматизация: Cron-задача для автоматической переигровки

Преимущества системы

  • 🤖 Полная автоматизация: Минимум ручной работы для админа
  • ⏱️ Справедливость: Четкий дедлайн для всех
  • 🔄 Эффективность: Призы не "зависают" у неактивных победителей
  • 📊 Прозрачность: Полная история всех действий
  • 🛡️ Безопасность: Только владелец может подтвердить
  • 💬 UX: Простая кнопка вместо сложной верификации

📞 Поддержка

Если что-то пошло не так:

  1. Проверьте логи бота
  2. Проверьте состояние БД (claimed_at, is_notified, is_claimed)
  3. Используйте /winner_status <id> для диагностики
  4. При критических ошибках - используйте /verify_winner для ручного подтверждения