Files
new_lottery_bot/ACCOUNT_SYSTEM_GUIDE.md
2025-11-15 20:03:49 +09:00

333 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Руководство по работе со счетами в розыгрышах
## Обзор
Теперь бот поддерживает два режима участия в розыгрышах:
1. **Старый режим**: участие пользователей по Telegram ID
2. **Новый режим**: участие по счетам формата `XX-XX-XX-XX-XX-XX-XX-XX`
## Формат счета
Счет состоит из **8 пар двухзначных чисел**, разделенных дефисом:
```
12-34-56-78-90-12-34-56
```
## Возможности для администраторов
### 1. Автоматическое обнаружение счетов
Когда администратор вводит в чат сообщение со счетами, бот автоматически обнаруживает их и предлагает действия:
**Пример:**
```
12-34-56-78-90-12-34-56
45-67-89-01-23-45-67-89
```
Бот выведет:
```
🔍 Обнаружен ввод счетов
Найдено: 2
• 12-34-56-78-90-12-34-56
• 45-67-89-01-23-45-67-89
Выберите действие:
[ Добавить в розыгрыш]
[👑 Сделать победителем]
[❌ Отмена]
```
### 2. Добавление счетов в розыгрыш
**Шаги:**
1. Введите счета (один или несколько с новой строки)
2. Нажмите " Добавить в розыгрыш"
3. Выберите розыгрыш из списка
4. Бот добавит все счета и покажет результат
**Результат:**
```
Результаты добавления в розыгрыш:
Новогодний розыгрыш 2025
✅ Добавлено: 15
⚠️ Пропущено: 3
Детали:
✅ 12-34-56-78-90-12-34-56
✅ 45-67-89-01-23-45-67-89
...
```
### 3. Установка победителя по счету
**Шаги:**
1. Введите **один** счет
2. Нажмите "👑 Сделать победителем"
3. Выберите розыгрыш
4. Выберите место (1, 2, 3...)
5. Бот установит победителя
**Пример:**
```
Ввод: 12-34-56-78-90-12-34-56
Результат:
✅ Победитель установлен!
Розыгрыш: Новогодний розыгрыш 2025
Счет: 12-34-56-78-90-12-34-56
Место: 1
Приз: iPhone 15 Pro
```
### 4. Множественный ввод счетов
Можно вводить несколько счетов одновременно:
```
12-34-56-78-90-12-34-56
45-67-89-01-23-45-67-89
11-22-33-44-55-66-77-88
99-88-77-66-55-44-33-22
```
Бот обнаружит все валидные счета и предложит массовые операции.
## Программный доступ
### Использование сервисов
```python
from account_services import AccountParticipationService
# Добавить счет в розыгрыш
async with async_session_maker() as session:
result = await AccountParticipationService.add_account_to_lottery(
session,
lottery_id=1,
account_number="12-34-56-78-90-12-34-56"
)
print(result["success"]) # True/False
print(result["message"]) # Сообщение о результате
# Массовое добавление
accounts = [
"12-34-56-78-90-12-34-56",
"45-67-89-01-23-45-67-89",
"11-22-33-44-55-66-77-88"
]
results = await AccountParticipationService.add_accounts_bulk(
session,
lottery_id=1,
accounts=accounts
)
print(f"Добавлено: {results['added']}")
print(f"Пропущено: {results['skipped']}")
print(f"Ошибки: {len(results['errors'])}")
# Получить все счета розыгрыша
accounts = await AccountParticipationService.get_lottery_accounts(
session,
lottery_id=1,
limit=100
)
# Установить победителя
result = await AccountParticipationService.set_account_as_winner(
session,
lottery_id=1,
account_number="12-34-56-78-90-12-34-56",
place=1,
prize="iPhone 15 Pro"
)
```
### Валидация счетов
```python
from account_utils import (
validate_account_number,
format_account_number,
parse_accounts_from_message
)
# Валидация
is_valid = validate_account_number("12-34-56-78-90-12-34-56") # True
is_valid = validate_account_number("12-34-56") # False
# Форматирование (очистка от лишних символов)
formatted = format_account_number("12 34 56 78 90 12 34 56")
# Результат: "12-34-56-78-90-12-34-56"
# Парсинг из текста
text = """
Вот счета для розыгрыша:
12-34-56-78-90-12-34-56
45-67-89-01-23-45-67-89
И ещё один: 11-22-33-44-55-66-77-88
"""
accounts = parse_accounts_from_message(text)
# Результат: ['12-34-56-78-90-12-34-56', '45-67-89-01-23-45-67-89', '11-22-33-44-55-66-77-88']
```
## Генерация тестовых счетов
```python
from account_utils import generate_account_number
# Генерация одного счета
account = generate_account_number()
print(account) # Например: "42-17-93-65-28-74-19-36"
# Генерация множества уникальных счетов
import random
def generate_unique_accounts(count=100):
accounts = set()
while len(accounts) < count:
accounts.add(generate_account_number())
return sorted(accounts)
accounts = generate_unique_accounts(100)
```
## Структура базы данных
### Таблица `participations`
```sql
CREATE TABLE participations (
id INTEGER PRIMARY KEY,
user_id INTEGER, -- Опционально (старый режим)
lottery_id INTEGER NOT NULL, -- ID розыгрыша
account_number VARCHAR(23), -- Счет (новый режим)
created_at DATETIME,
FOREIGN KEY(user_id) REFERENCES users (id),
FOREIGN KEY(lottery_id) REFERENCES lotteries (id)
)
```
### Таблица `winners`
```sql
CREATE TABLE winners (
id INTEGER PRIMARY KEY,
lottery_id INTEGER NOT NULL,
user_id INTEGER, -- Опционально (старый режим)
account_number VARCHAR(23), -- Счет победителя (новый режим)
place INTEGER NOT NULL, -- Место (1, 2, 3...)
prize VARCHAR(500), -- Описание приза
is_manual BOOLEAN, -- Установлен вручную?
created_at DATETIME,
FOREIGN KEY(lottery_id) REFERENCES lotteries (id),
FOREIGN KEY(user_id) REFERENCES users (id)
)
```
## Совместимость
- ✅ Старый режим (участие пользователей) продолжает работать
- ✅ Новый режим (участие счетов) работает параллельно
-В одном розыгрыше могут быть как пользователи, так и счета
- ✅ Поддержка обоих режимов для победителей
## Примеры использования
### Пример 1: Добавление счетов через чат
**Администратор пишет:**
```
12-34-56-78-90-12-34-56
45-67-89-01-23-45-67-89
11-22-33-44-55-66-77-88
```
**Бот отвечает:**
```
🔍 Обнаружен ввод счетов
Найдено: 3
...
```
**Администратор выбирает:**
1. "Добавить в розыгрыш"
2. Выбирает "Новогодний розыгрыш 2025"
**Бот добавляет все 3 счета**
### Пример 2: Установка победителя
**Администратор пишет:**
```
12-34-56-78-90-12-34-56
```
**Бот отвечает:**
```
🔍 Обнаружен ввод счета
Найдено: 1
```
**Администратор выбирает:**
1. "Сделать победителем"
2. Выбирает розыгрыш
3. Выбирает "Место 1: iPhone 15 Pro"
**Бот устанавливает победителя**
## API endpoints (в коде)
| Сервис | Метод | Описание |
|--------|-------|----------|
| `AccountParticipationService` | `add_account_to_lottery` | Добавить счет |
| | `add_accounts_bulk` | Массовое добавление |
| | `remove_account_from_lottery` | Удалить счет |
| | `get_lottery_accounts` | Получить все счета |
| | `get_accounts_count` | Количество счетов |
| | `set_account_as_winner` | Установить победителя |
| | `get_lottery_winners_accounts` | Получить победителей |
## Технические детали
- **Валидация**: Счет должен содержать ровно 8 пар двухзначных чисел
- **Форматирование**: Автоматическая очистка от лишних пробелов и символов
- **Индексация**: Поле `account_number` индексировано для быстрого поиска
- **Уникальность**: Один счет не может участвовать в одном розыгрыше дважды
- **Поддержка NULL**: `user_id` и `account_number` могут быть NULL
## Миграция данных
При обновлении проекта:
1. Создайте резервную копию базы данных
2. Запустите миграции или пересоздайте БД:
```bash
make migrate
# или
rm -f lottery_bot.db && python -c "import asyncio; from database import init_db; asyncio.run(init_db())"
```
## Troubleshooting
### Бот не обнаруживает счета
**Проблема:** Введен неверный формат
**Решение:** Убедитесь, что счет в формате `XX-XX-XX-XX-XX-XX-XX-XX` (8 пар)
### Счет не добавляется
**Проблема:** Счет уже участвует в розыгрыше
**Решение:** Проверьте список участников розыгрыша
### Ошибка при установке победителя
**Проблема:** Счет не участвует в розыгрыше
**Решение:** Сначала добавьте счет в розыгрыш, затем установите победителем