# 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-бота! 🚀