main functions fix

This commit is contained in:
2025-11-15 20:03:49 +09:00
parent e0075d91b6
commit 3a25e6a4cb
18 changed files with 1779 additions and 75 deletions

332
ACCOUNT_SYSTEM_GUIDE.md Normal file
View File

@@ -0,0 +1,332 @@
# Руководство по работе со счетами в розыгрышах
## Обзор
Теперь бот поддерживает два режима участия в розыгрышах:
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 пар)
### Счет не добавляется
**Проблема:** Счет уже участвует в розыгрыше
**Решение:** Проверьте список участников розыгрыша
### Ошибка при установке победителя
**Проблема:** Счет не участвует в розыгрыше
**Решение:** Сначала добавьте счет в розыгрыш, затем установите победителем