""" Обработчики команд управления администраторами """ from aiogram import Router, F from aiogram.filters import Command from aiogram.types import Message, CallbackQuery from aiogram.utils.keyboard import InlineKeyboardBuilder from bot import bot # ← ДОБАВЬ ЭТОТ ИМПОРТ from bot.filters.admin import IsSuperAdmin from configs import settings, COMMANDS from database import get_manager from middleware.loggers import logger from bot.utils import log_action, tg_emoji __all__ = ("router",) router: Router = Router(name="admin_management_router") def parse_user_id(text: str, command: str) -> tuple[bool, str | int]: parts = text.split(maxsplit=1) if len(parts) < 2: return False, f'{tg_emoji("4961187972822074653")} Использование: /{command} ' user_id_str = parts[1].strip() try: user_id = int(user_id_str) if user_id <= 0: return False, f'{tg_emoji("4961187972822074653")} ID должен быть положительным числом' if user_id > 9999999999: return False, f'{tg_emoji("4961187972822074653")} Некорректный ID пользователя' return True, user_id except ValueError: return False, f'{tg_emoji("4961187972822074653")} ID должен быть числом' async def get_user_display_name(user_id: int) -> str: """Получает имя пользователя или username или ID""" try: chat = await bot.get_chat(user_id) name = f"{chat.first_name or ''} {chat.last_name or ''}".strip() if name: return name if chat.username: return f"@{chat.username}" return str(user_id) except: return str(user_id) def format_admin_info(user_id: int, username: str | None = None) -> str: if username: return f'{user_id} (@{username})' return f'{user_id}' def get_refresh_admins_kb(): ikb = InlineKeyboardBuilder() ikb.button(text='🔄 Обновить', callback_data='listadmins:refresh') ikb.button(text='➕ Добавить', callback_data='admin:help_add') ikb.adjust(2) return ikb.as_markup() # ================= ДОБАВЛЕНИЕ АДМИНИСТРАТОРА ================= @router.message(Command(*COMMANDS.get('addadmin', ['addadmin']), prefix=settings.PREFIX, ignore_case=True), IsSuperAdmin()) @log_action(action_name='ADD_ADMIN', log_args=True) async def add_admin_cmd(message: Message) -> None: success, result = parse_user_id(message.text, 'addadmin') if not success: await message.answer(result, parse_mode='HTML') return user_id = result if user_id == message.from_user.id: await message.answer( f'{tg_emoji("4963024861615096794")} Вы уже владелец бота\n\n' 'Вам не нужно добавлять себя в администраторы', parse_mode='HTML' ) return if user_id in settings.OWNER_ID: await message.answer( f'{tg_emoji("4963024861615096794")} Этот пользователь уже владелец бота\n\n' 'Владельцы имеют полные права автоматически', parse_mode='HTML' ) return manager = get_manager() try: is_already_admin = await manager.is_admin(user_id) if is_already_admin: display_name = await get_user_display_name(user_id) await message.answer( f'{tg_emoji("4963024861615096794")} Пользователь {display_name} уже является администратором', parse_mode='HTML' ) return added = await manager.add_admin(user_id=user_id, added_by=message.from_user.id) if added: display_name = await get_user_display_name(user_id) text = ( f'{tg_emoji("4963010134172239128")} Администратор добавлен\n\n' f'{tg_emoji("4961064956368782417")} ID: {format_admin_info(user_id)}\n' f'{tg_emoji("4963343509533754468")} Имя: {display_name}\n' f'{tg_emoji("4963343509533754468")} Добавил: {format_admin_info(message.from_user.id, message.from_user.username)}\n\n' f'{tg_emoji("4961106084975608869")} Права администратора:\n' f'├─ Управление банвордами\n' f'├─ Просмотр статистики\n' f'├─ Активация режимов модерации\n' f'└─ Все команды бота\n\n' f'{tg_emoji("4963024861615096794")} Не может управлять другими админами\n' f'Список админов: /listadmins' ) logger.info(f'Администратор добавлен: {user_id} (добавил: {message.from_user.id})', log_type='ADMIN_MGMT') else: text = f'{tg_emoji("4961187972822074653")} Ошибка добавления администратора\n\nПопробуйте позже' await message.answer(text, parse_mode='HTML') except Exception as e: logger.error(f'Ошибка добавления администратора: {e}', log_type='ADMIN_MGMT') await message.answer(f'{tg_emoji("4961187972822074653")} Ошибка добавления\n\nПопробуйте позже', parse_mode='HTML') # ================= УДАЛЕНИЕ АДМИНИСТРАТОРА ================= @router.message(Command(*COMMANDS.get('remadmin', ['remadmin']), prefix=settings.PREFIX, ignore_case=True), IsSuperAdmin()) @log_action(action_name='REMOVE_ADMIN', log_args=True) async def remove_admin_cmd(message: Message) -> None: success, result = parse_user_id(message.text, 'remadmin') if not success: await message.answer(result, parse_mode='HTML') return user_id = result if user_id in settings.OWNER_ID: await message.answer( f'{tg_emoji("4963024861615096794")} Нельзя удалить владельца\n\n' 'Владельцы имеют права постоянно', parse_mode='HTML' ) return if user_id == message.from_user.id: await message.answer( f'{tg_emoji("4963024861615096794")} Нельзя удалить самого себя', parse_mode='HTML' ) return manager = get_manager() try: is_admin = await manager.is_admin(user_id) if not is_admin: display_name = await get_user_display_name(user_id) await message.answer( f'{tg_emoji("4963024861615096794")} Пользователь {display_name} не является администратором', parse_mode='HTML' ) return removed = await manager.remove_admin(user_id=user_id) if removed: display_name = await get_user_display_name(user_id) text = ( f'🗑 Администратор удалён\n\n' f'{tg_emoji("4961064956368782417")} ID: {format_admin_info(user_id)}\n' f'{tg_emoji("4961064956368782417")} Имя: {display_name}\n' f'{tg_emoji("4963343509533754468")} Удалил: {format_admin_info(message.from_user.id, message.from_user.username)}\n\n' f'{tg_emoji("4963024861615096794")} Пользователь больше не имеет доступа к командам бота' ) logger.info(f'Администратор удалён: {user_id} (удалил: {message.from_user.id})', log_type='ADMIN_MGMT') else: text = f'{tg_emoji("4961187972822074653")} Ошибка удаления администратора\n\nПопробуйте позже' await message.answer(text, parse_mode='HTML') except Exception as e: logger.error(f'Ошибка удаления администратора: {e}', log_type='ADMIN_MGMT') await message.answer(f'{tg_emoji("4961187972822074653")} Ошибка удаления\n\nПопробуйте позже', parse_mode='HTML') # ================= СПИСОК АДМИНИСТРАТОРОВ ================= @router.callback_query(F.data == 'listadmins:refresh') @router.message(Command(*COMMANDS.get('listadmins', ['listadmins']), prefix=settings.PREFIX, ignore_case=True), IsSuperAdmin()) @log_action(action_name='LIST_ADMINS') async def list_admins_cmd(update: Message | CallbackQuery) -> None: if isinstance(update, CallbackQuery): message = update.message is_callback = True else: message = update is_callback = False manager = get_manager() try: db_admins = await manager.repo.get_admins() output = f'{tg_emoji("4960891456869893259")} СПИСОК АДМИНИСТРАТОРОВ\n\n' # ВЛАДЕЛЬЦЫ output += f'{tg_emoji("4963343509533754468")} Владельцы бота (полные права):\n' for owner_id in settings.OWNER_ID: display_name = await get_user_display_name(owner_id) output += f'├─ {display_name}\n' output += '\n' # АДМИНИСТРАТОРЫ if db_admins: output += f'{tg_emoji("4961064956368782417")} Администраторы ({len(db_admins)}):\n' for admin_id in sorted(db_admins): display_name = await get_user_display_name(admin_id) output += f'├─ {display_name}\n' output += '\n' output += f'{tg_emoji("4961106084975608869")} Права администраторов:\n' output += '├─ Управление банвордами\n' output += '├─ Просмотр статистики\n' output += '├─ Активация режимов модерации\n' output += '└─ Все команды бота\n\n' else: output += f'{tg_emoji("4961064956368782417")} Администраторы:\n' output += '└─ Нет дополнительных администраторов\n\n' total_admins = len(settings.OWNER_ID) + len(db_admins) output += f'{tg_emoji("4961061266991875258")} Итого: {total_admins} администратор(ов)\n\n' output += f'{tg_emoji("4961027057577362562")} Управление:\n' output += '• /adminhelp — помощь по командам админов\n' output += '• /addadmin ID — добавить админа\n' output += '• /remadmin ID — удалить админа\n\n' output += f'{tg_emoji("4961186405159011104")} Только владельцы могут управлять администраторами' keyboard = get_refresh_admins_kb() if is_callback: await message.edit_text(text=output, parse_mode='HTML', reply_markup=keyboard) await update.answer(f'{tg_emoji("4963010134172239128")} Список обновлён') else: await message.answer(text=output, parse_mode='HTML', reply_markup=keyboard) except Exception as e: logger.error(f'Ошибка получения списка администраторов: {e}', log_type='ADMIN_MGMT') error_text = f'{tg_emoji("4961187972822074653")} Ошибка загрузки списка\n\nПопробуйте позже' if is_callback: await update.answer(f'{tg_emoji("4961187972822074653")} Ошибка загрузки', show_alert=True) else: await message.answer(error_text, parse_mode='HTML') # ================= ВСПОМОГАТЕЛЬНЫЕ CALLBACK ================= @router.callback_query(F.data == 'admin:help_add') async def admin_help_add_callback(callback: CallbackQuery) -> None: text = ( f'{tg_emoji("4963469772982322370")} Как добавить администратора?\n\n' f'{tg_emoji("4960889107522782272")} Узнайте Telegram ID пользователя\n' ' • Используйте команду /id или бота @userinfobot\n' f'{tg_emoji("4960889107522782272")} Выполните команду:\n' ' /addadmin ID\n\n' 'Пример:\n' '/addadmin 123456789' ) await callback.answer() await callback.message.answer(text, parse_mode='HTML') @router.message(Command(*COMMANDS.get('adminhelp', ['adminhelp']), prefix=settings.PREFIX, ignore_case=True), IsSuperAdmin()) async def admin_help_cmd(message: Message) -> None: text = ( f'{tg_emoji("4960891456869893259")} УПРАВЛЕНИЕ АДМИНИСТРАТОРАМИ\n\n' f'{tg_emoji("4963401727815451692")} Уровни доступа:\n\n' f'{tg_emoji("4963343509533754468")} Владельцы (OWNER_ID):\n' '├─ Все права администратора\n' '├─ Управление другими админами\n' '└─ Указываются в конфигурации\n\n' f'{tg_emoji("4961064956368782417")} Администраторы:\n' '├─ Управление банвордами\n' '├─ Просмотр статистики\n' '├─ Активация режимов модерации\n' '└─ Не могут управлять админами\n\n' f'{tg_emoji("4963241130398319816")} Команды:\n' '• /adminhelp — помощь по командам админов\n' '• /listadmins — список всех админов\n' '• /addadmin ID — добавить админа\n' '• /remadmin ID — удалить админа\n\n' f'{tg_emoji("4961186405159011104")} Как узнать ID пользователя?\n' '• Используйте команду /id или бота @userinfobot\n' '• Или попросите пользователя написать боту\n' '• ID отображается в логах бота\n\n' f'{tg_emoji("4963024861615096794")} Важно:\n' '├─ Нельзя удалить владельца\n' '├─ Нельзя удалить самого себя\n' '└─ Все действия логируются' ) await message.answer(text, parse_mode='HTML') @router.message(Command(*COMMANDS.get('checkadmin', ['checkadmin']), prefix=settings.PREFIX, ignore_case=True), IsSuperAdmin()) @log_action(action_name='CHECK_ADMIN') async def check_admin_cmd(message: Message) -> None: success, result = parse_user_id(message.text, 'checkadmin') if not success: await message.answer(result, parse_mode='HTML') return user_id = result manager = get_manager() try: is_owner = user_id in settings.OWNER_ID is_db_admin = await manager.is_admin(user_id) text = f'{tg_emoji("4961092195051373778")} Проверка пользователя\n\n' text += f'{tg_emoji("4961064956368782417")} ID: {user_id}\n\n' if is_owner: text += f'{tg_emoji("4963343509533754468")} Статус: Владелец бота\n' text += f'{tg_emoji("4963010134172239128")} Полные права администратора\n' text += f'{tg_emoji("4963010134172239128")} Может управлять админами' elif is_db_admin: text += f'{tg_emoji("4961064956368782417")} Статус: Администратор\n' text += f'{tg_emoji("4963010134172239128")} Доступ к командам бота\n' text += f'{tg_emoji("4961187972822074653")} Не может управлять админами' else: text += f'{tg_emoji("4961064956368782417")} Статус: Обычный пользователь\n' text += f'{tg_emoji("4961187972822074653")} Нет прав администратора\n\n' text += f'Добавить в админы: /addadmin {user_id}' await message.answer(text, parse_mode='HTML') except Exception as e: logger.error(f'Ошибка проверки администратора: {e}', log_type='ADMIN_MGMT') await message.answer(f'{tg_emoji("4961187972822074653")} Ошибка проверки', parse_mode='HTML')