Files
balance_bot/README.md
2026-01-23 04:45:55 +07:00

502 lines
26 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# PrimoExampleBot
Конечно. Давай разберём весь твой класс `BotDatabase` и методы, и покажу **как использовать каждый метод на практике** с аннотациями и примерами. Я постараюсь дать максимально ясное объяснение, чтобы можно было сразу применять в aiogram-боте.
---
## 1⃣ Инициализация базы данных
```python
db: BotDatabase = BotDatabase() # создаём экземпляр класса
await db.setup() # создаёт все таблицы в SQLite (users, user_messages, roles)
```
* `init_db()` автоматически создаёт таблицы, если их нет.
* Вызывается один раз при старте бота.
---
## 2⃣ Работа с пользователями
### Добавление пользователя вручную
```python
await db.add_user(
user_id=12345,
username="alex",
full_name="Alex Test",
is_admin=True
)
```
* `user_id` — Telegram ID пользователя.
* `username` — никнейм Telegram.
* `full_name` — полное имя.
* `is_admin` — если True, пользователь получает статус `ADMIN`, иначе `ACTIVE`.
---
### Бан и разбан пользователя
```python
await db.ban_user(12345) # забанить
await db.unban_user(12345) # разбанить
```
* Статусы хранятся в Enum `UserStatus` (`ACTIVE`, `ADMIN`, `BANNED`).
* Можно применять фильтры при выборке пользователей, чтобы исключать забаненных.
---
### Получение списка ID пользователей
```python
ids: List[int] = await db.get_user_ids(
only_active=True, # исключаем забаненных
include_admins=False, # исключаем админов
order_asc=True # сортировка по возрастанию
)
```
* Возвращает чистый `List[int]` Telegram ID, чтобы можно было делать рассылку сообщений.
* Можно исключать забаненных и/или админов.
---
## 3⃣ Работа с сообщениями
### Добавление сообщения пользователя
```python
await db.add_message(user_id=12345, message_text="Привет!")
```
* Если пользователя нет в базе — создаётся новая запись.
* Сообщение автоматически связывается с пользователем через `UserMessage`.
---
### Статистика сообщений
```python
day, week, month, total = await db.get_message_stats(user_id=12345)
print(f"За день: {day}, за неделю: {week}, за месяц: {month}, всего: {total}")
```
* Возвращает кортеж `(день, неделя, месяц, всё время)`.
* Неделя считается **с понедельника по текущий день**, месяц — последние 30 дней.
---
## 4⃣ Работа с ролями
### Инициализация ролей
```python
await db.init_roles(["Альбедо", "Чжун Ли", "Кэйа"])
```
* Создаёт роли, если их нет.
* Используется один раз при настройке базы или при добавлении новых персонажей.
---
### Назначение роли пользователю
```python
success: bool = await db.assign_role("Альбедо", user_id=12345)
if success:
print("Роль назначена!")
else:
print("Роль уже занята")
```
* Возвращает `True`, если роль успешно назначена.
* Если роль уже занята — возвращает `False`.
---
### Освобождение роли
```python
await db.release_role("Альбедо")
```
* Делает `occupied_by = None`.
* Позволяет передать роль другому пользователю.
---
### Получение статуса всех ролей
```python
roles: List[Tuple[str, Optional[int]]] = await db.get_role_status()
for role_name, user_id in roles:
print(f"{role_name} занята пользователем {user_id}")
```
* Возвращает список кортежей `(имя роли, user_id или None)`.
* Полезно для отображения в админ-панели бота.
---
### Получение ролей конкретного пользователя
```python
roles_for_user: List[str] = await db.get_roles_by_user(user_id=12345)
print("Пользователь занимает роли:", roles_for_user)
```
* Возвращает все имена ролей, которые занимает конкретный пользователь.
---
## 5⃣ Примеры типичного использования в aiogram
```python
from aiogram import Bot, Dispatcher, types
@dp.message_handler(commands=["start"])
async def cmd_start(message: types.Message):
# автоматически добавляем пользователя в базу
await db.add_user(
user_id=message.from_user.id,
username=message.from_user.username,
full_name=message.from_user.full_name
)
await message.answer("Привет! Ты добавлен в базу.")
@dp.message_handler(commands=["stats"])
async def cmd_stats(message: types.Message):
day, week, month, total = await db.get_message_stats(message.from_user.id)
await message.answer(
f"Сообщения:\nЗа день: {day}\nЗа неделю: {week}\nЗа месяц: {month}\nВсего: {total}"
)
@dp.message_handler()
async def all_messages(message: types.Message):
# сохраняем любое сообщение пользователя
await db.add_message(message.from_user.id, message.text)
```
* В этом примере база автоматически создаёт пользователя при первом сообщении.
* Любые сообщения сохраняются для статистики.
* Можно легко подключить роли и рассылку по ID пользователей.
---
# Сохранение сообщений с ролями
```python
await db.save_role_message(
game_type="genshin",
channel_id=CHANNEL_ID,
message_id=MESSAGE_ID,
message_text="Текст сообщения с персонажами Genshin..."
)
```
```python
# Для Honkai: Star Rail
await db.save_role_message(
game_type="hsr",
channel_id=CHANNEL_ID,
message_id=MESSAGE_ID,
message_text="Текст сообщения с персонажами HSR..."
)
```
# 🎯 4. Назначение и освобождение ролей
```python
# Назначение роли (автоматически определит игру по региону)
success = await db.assign_role("Альбедо", user_id, bot) # Genshin
success = await db.assign_role("Вельт", user_id, bot) # HSR
# Освобождение роли
success = await db.release_role("Альбедо", bot) # Genshin
success = await db.release_role("Вельт", bot) # HSR
```
# 📊 5. Получение статистики по регионам
```python
# Для Genshin Impact
mondstadt_roles = await db.get_roles_by_region(RoleRegion.MONDSTADT)
liyue_roles = await db.get_roles_by_region(RoleRegion.LIYUE)
# Для Honkai: Star Rail
star_express_roles = await db.get_roles_by_region(RoleRegion.HSR_STAR)
lofu_roles = await db.get_roles_by_region(RoleRegion.HSR_LOFU)
```
# 🔍 6. Поиск ролей
```python
# Найти роль по имени
role = await db.get_role_by_name("Альбедо")
if role:
print(f"Персонаж: {role.name}, Регион: {role.region}, Занята: {role.occupied_by is not None}")
# Получить все свободные роли в регионе
free_roles = await db.get_available_roles(RoleRegion.MONDSTADT)
```
# 📝 7. Обновление сообщений вручную
```python
# Обновить сообщение с персонажами Genshin
await db.update_role_message("genshin", bot)
# Обновить сообщение с персонажами HSR
await db.update_role_message("hsr", bot)
```
# 🎮 8. Как система определяет игру для роли
Система автоматически определяет к какой игре принадлежит роль на основе региона:
Все регионы Genshin Impact (от MONDSTADT до OTHER) → игра "genshin"
Все регионы HSR (начинающиеся с HSR_) → игра "hsr"
---
Отлично! Ваша база данных очень мощная и имеет множество функций. Давайте разберем все возможности по категориям:
## 📊 **1. Статистика сообщений пользователя**
### Получение статистики за разные периоды:
```python
# Получить статистику сообщений пользователя
day, week, month, total = await db.get_message_stats(user_id)
print(f"За день: {day} сообщений")
print(f"За неделю: {week} сообщений")
print(f"За месяц: {month} сообщений")
print(f"Всего: {total} сообщений")
```
### Пример использования в хендлере:
```python
@dp.message_handler(commands=["stats"])
async def stats_handler(message: Message):
user_id = message.from_user.id
day, week, month, total = await db.get_message_stats(user_id)
text = (
f"📊 Ваша статистика сообщений:\n"
f"За день: {day}\n"
f"За неделю: {week}\n"
f"За месяц: {month}\n"
f"Всего: {total}"
)
await message.answer(text)
```
## 👥 **2. Управление пользователями**
### Добавление/получение пользователей:
```python
# Добавить пользователя
await db.add_user(
user_id=123456789,
username="username",
full_name="Имя Фамилия",
is_admin=False # или True для админа
)
# Получить пользователя
user = await db.get_user(123456789)
if user:
print(f"Имя: {user.full_name}, Статус: {user.status}")
# Получить всех пользователей
users = await db.get_all_users(include_banned=False)
for user in users:
print(f"{user.id}: {user.username}")
# Получить ID всех пользователей (для рассылки)
user_ids = await db.get_user_ids(only_active=True, include_admins=True)
```
### Бан/разбан:
```python
# Забанить пользователя
await db.ban_user(user_id)
# Разбанить пользователя
await db.unban_user(user_id)
# Сделать админом
await db.set_admin(user_id, make_admin=True)
# Убрать админку
await db.set_admin(user_id, make_admin=False)
```
## 💬 **3. Работа с сообщениями**
### Сохранение сообщений:
```python
# Вручную добавить сообщение
await db.add_message(
user_id=123456789,
message_text="Текст сообщения",
created_at=datetime.now(timezone.utc) # опционально
)
# Автоматически из aiogram сообщения
await db.add_message_from_message(message)
```
## 🎭 **4. Система ролей (персонажей)**
### Инициализация ролей:
```python
# Инициализировать стандартные роли
await db.init_default_roles()
# Или создать свои роли
roles = [
("Альбедо", RoleRegion.MONDSTADT),
("Нахида", RoleRegion.SUMERU),
("Кафка", RoleRegion.HSR_STAR)
]
await db.init_roles(roles)
```
### Работа с ролями:
```python
# Назначить роль пользователю
success = await db.assign_role("Альбедо", user_id, bot)
if success:
print("Роль назначена!")
# Освободить роль
success = await db.release_role("Альбедо", bot)
# Получить все роли пользователя
user_roles = await db.get_roles_by_user(user_id)
print(f"Ваши роли: {', '.join(user_roles)}")
# Посмотреть статус всех ролей
all_roles = await db.get_role_status()
for role_name, occupied_by in all_roles:
status = "✅ занята" if occupied_by else "❌ свободна"
print(f"{role_name}: {status}")
# Найти свободные роли в регионе
free_roles = await db.get_available_roles(RoleRegion.MONDSTADT)
for role in free_roles:
print(role.name)
# Получить информацию о конкретной роли
role = await db.get_role_by_name("Альбедо")
if role:
print(f"Регион: {role.region}, Занята: {role.occupied_by is not None}")
```
### Статистика по регионам:
```python
# Получить статистику по всем регионам
stats = await db.get_region_stats()
for region, data in stats.items():
print(f"{region}: {data['free']} свободно, {data['occupied']} занято")
```
## 📝 **5. Управление сообщениями с ролями в каналах**
```python
# Сохранить информацию о сообщении с ролями
await db.save_role_message(
game_type="genshin", # или "hsr"
channel_id=-100123456789,
message_id=123,
message_text="Список персонажей Genshin Impact"
)
# Обновить сообщение с ролями (после назначения/освобождения)
await db.update_role_message("genshin", bot)
```
## 🛠 **6. Сервисные функции**
```python
# Инициализация базы данных
await db.setup()
# Проверка соединения
if await db.check_connection():
print("База данных подключена")
# Корректное закрытие соединений
await db.dispose()
```
## 🎯 **Практические примеры использования:**
### 1. **Команда для просмотра статистики**
```python
@dp.message_handler(commands=["my_stats"])
async def my_stats_handler(message: Message):
user_id = message.from_user.id
day, week, month, total = await db.get_message_stats(user_id)
text = (
"📊 Ваша активность в чатах:\n"
f"• Сегодня: {day} сообщений\n"
f"За неделю: {week} сообщений\n"
f"За месяц: {month} сообщений\n"
f"Всего: {total} сообщений"
)
await message.answer(text)
```
### 2. **Команда для просмотра ролей**
```python
@dp.message_handler(commands=["my_roles"])
async def my_roles_handler(message: Message):
user_id = message.from_user.id
roles = await db.get_roles_by_user(user_id)
if roles:
text = "🎭 Ваши роли:\n" + "\n".join(roles)
else:
text = "У вас пока нет ролей. Используйте /roles чтобы посмотреть доступные."
await message.answer(text)
```
### 3. **Команда для админов - статистика чата**
```python
@dp.message_handler(commands=["chat_stats"], is_admin=True)
async def chat_stats_handler(message: Message):
users = await db.get_all_users(include_banned=False)
total_messages = 0
user_stats = []
for user in users:
day, week, month, total = await db.get_message_stats(user.id)
total_messages += total
user_stats.append((user, total))
# Сортировка по активности
user_stats.sort(key=lambda x: x[1], reverse=True)
text = "📈 Статистика чата:\n"
text += f"Всего пользователей: {len(users)}\n"
text += f"Всего сообщений: {total_messages}\n\n"
text += "🏆 Топ-5 активных пользователей:\n"
for i, (user, count) in enumerate(user_stats[:5], 1):
username = user.username or user.full_name or f"ID {user.id}"
text += f"{i}. {username}: {count} сообщений\n"
await message.answer(text)
```
Ваша база данных отлично спроектирована и покрывает все основные потребности Telegram-бота! 🚀