from aiogram import Router from aiogram.filters import Command from aiogram.fsm.context import FSMContext from aiogram.types import Message, User from html import escape from bot import bot from bot.filters import IsAdmin from bot.utils import status_clear from configs import COMMANDS # Настройки роутера __all__ = ("router",) from middleware import logger CMD: str = "kick" router: Router = Router(name=f"{CMD}_cmd_router") @router.message(Command(*COMMANDS[CMD], ignore_case=True), IsAdmin()) async def kick_user_cmd(message: Message, state: FSMContext) -> None: """ Команда /kick для кика пользователей из чата. Использование: /kick или ответ на сообщение пользователя + /kick """ await status_clear(update=message, state=state) # Проверяем, что команда используется в группе/супергруппе if message.chat.type not in ["group", "supergroup"]: await message.answer("❌ Эта команда работает только в группах и супергруппах!") return # Проверяем есть ли ответ на сообщение if message.reply_to_message: # Кик по ответу на сообщение target_user: User | None = message.reply_to_message.from_user target_user_id: int = target_user.id target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}" # Кикаем пользователя success: bool = await _kick_user(target_user_id, target_username, message) if success: safe_username: str = escape(target_username) await message.answer( text=f"👢 Пользователь {safe_username} (ID: {target_user_id}) кикнут из чата!", ) else: await message.answer("❌ Не удалось кикнуть пользователя") else: # Кик по ID пользователя command_parts: list[str] = message.text.split() if len(command_parts) < 2: await message.answer( "ℹ️ Использование команды:\n" "• Ответьте на сообщение пользователя командой /kick\n" "• Или укажите ID: /kick " ) return try: target_user_id: int = int(command_parts[1]) success: bool = await _kick_user(target_user_id, f"ID{target_user_id}", message) if success: await message.answer( text=f"👢 Пользователь (ID: {target_user_id}) кикнут из чата!", parse_mode=None # Отключаем разметку ) else: await message.answer("❌ Пользователь не найден или не удалось кикнуть") except ValueError: await message.answer("❌ Неверный формат ID пользователя") async def _kick_user(user_id: int, username: str, message: Message) -> bool: """ Внутренняя функция для кика пользователя из чата. Args: user_id: ID пользователя для кика username: Имя пользователя для логов message: Объект сообщения для контекста Returns: bool: Успешно ли кикнут пользователь """ try: # Проверяем, что бот имеет права администратора в чате bot_member = await bot.get_chat_member(message.chat.id, bot.id) if not bot_member.can_restrict_members: await message.answer("❌ У меня нет прав для кика пользователей!") return False # Проверяем, что целевой пользователь не является администратором/владельцем target_member = await bot.get_chat_member(message.chat.id, user_id) if target_member.status in ["creator", "administrator"]: await message.answer("❌ Нельзя кикнуть администратора или создателя чата!") return False # Проверяем, что отправитель команды имеет права администратора admin_member = await bot.get_chat_member(message.chat.id, message.from_user.id) if admin_member.status not in ["creator", "administrator"]: await message.answer("❌ У вас нет прав для кика пользователей!") return False # Кикаем пользователя из чата await bot.ban_chat_member( chat_id=message.chat.id, user_id=user_id, revoke_messages=False # Не удаляем сообщения пользователя ) # Сразу разбаниваем, чтобы пользователь мог вернуться по приглашению await bot.unban_chat_member( chat_id=message.chat.id, user_id=user_id ) # Логируем действие admin_username = message.from_user.username or message.from_user.full_name logger.info( f"👢 Админ @{admin_username} кикнул пользователя @{username} (ID: {user_id}) из чата {message.chat.title}") return True except Exception as e: logger.error(f"❌ Ошибка при кике пользователя {user_id}: {e}") await message.answer(f"❌ Ошибка при кике пользователя: {str(e)}") return False @router.message(Command("kick_ban", ignore_case=True), IsAdmin()) async def kick_ban_user_cmd(message: Message, state: FSMContext) -> None: """ Команда /kick_ban для кика пользователя с удалением сообщений. Использование: /kick_ban или ответ на сообщение пользователя + /kick_ban """ await status_clear(update=message, state=state) # Проверяем, что команда используется в группе/супергруппе if message.chat.type not in ["group", "supergroup"]: await message.answer("❌ Эта команда работает только в группах и супергруппах!") return # Проверяем есть ли ответ на сообщение if message.reply_to_message: # Кик по ответу на сообщение target_user: User | None = message.reply_to_message.from_user target_user_id: int = target_user.id target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}" # Кикаем пользователя с удалением сообщений success: bool = await _kick_ban_user(target_user_id, target_username, message) if success: safe_username: str = escape(target_username) await message.answer( text=f"💥 Пользователь {safe_username} (ID: {target_user_id}) кикнут с удалением сообщений!", parse_mode=None # Отключаем разметку ) else: await message.answer("❌ Не удалось кикнуть пользователя") else: # Кик по ID пользователя command_parts: list[str] = message.text.split() if len(command_parts) < 2: await message.answer( "ℹ️ Использование команды:\n" "• Ответьте на сообщение пользователя командой /kick_ban\n" "• Или укажите ID: /kick_ban " ) return try: target_user_id: int = int(command_parts[1]) success: bool = await _kick_ban_user(target_user_id, f"ID{target_user_id}", message) if success: await message.answer( text=f"💥 Пользователь (ID: {target_user_id}) кикнут с удалением сообщений!", parse_mode=None # Отключаем разметку ) else: await message.answer("❌ Пользователь не найден или не удалось кикнуть") except ValueError: await message.answer("❌ Неверный формат ID пользователя") async def _kick_ban_user(user_id: int, username: str, message: Message) -> bool: """ Внутренняя функция для кика пользователя с удалением сообщений. Args: user_id: ID пользователя для кика username: Имя пользователя для логов message: Объект сообщения для контекста Returns: bool: Успешно ли кикнут пользователь """ try: # Проверяем, что бот имеет права администратора в чате bot_member = await bot.get_chat_member(message.chat.id, bot.id) if not bot_member.can_restrict_members: await message.answer("❌ У меня нет прав для кика пользователей!") return False # Проверяем, что целевой пользователь не является администратором/владельцем target_member = await bot.get_chat_member(message.chat.id, user_id) if target_member.status in ["creator", "administrator"]: await message.answer("❌ Нельзя кикнуть администратора или создателя чата!") return False # Проверяем, что отправитель команды имеет права администратора admin_member = await bot.get_chat_member(message.chat.id, message.from_user.id) if admin_member.status not in ["creator", "administrator"]: await message.answer("❌ У вас нет прав для кика пользователей!") return False # Кикаем пользователя из чата с удалением сообщений await bot.ban_chat_member( chat_id=message.chat.id, user_id=user_id, revoke_messages=True # Удаляем сообщения пользователя ) # Сразу разбаниваем, чтобы пользователь мог вернуться по приглашению await bot.unban_chat_member( chat_id=message.chat.id, user_id=user_id ) # Логируем действие admin_username = message.from_user.username or message.from_user.full_name logger.info( f"💥 Админ @{admin_username} кикнул пользователя @{username} (ID: {user_id}) из чата {message.chat.title} с удалением сообщений") return True except Exception as e: logger.error(f"❌ Ошибка при кике пользователя {user_id} с удалением сообщений: {e}") await message.answer(f"❌ Ошибка при кике пользователя: {str(e)}") return False @router.message(Command("kick_list", ignore_case=True), IsAdmin()) async def kick_help_cmd(message: Message, state: FSMContext) -> None: """ Команда /kick_list для показа справки по командам кика. """ await status_clear(update=message, state=state) help_text = """ 🤖 **Команды модерации:** **👢 /kick** - Кикнуть пользователя (может вернуться по приглашению) • Ответьте на сообщение пользователя с командой /kick • Или используйте: /kick **💥 /kick_ban** - Кикнуть пользователя с удалением сообщений • Ответьте на сообщение пользователя с командой /kick_ban • Или используйте: /kick_ban **🚫 /ban** - Полностью забанить пользователя **🔓 /unban** - Разбанить пользователя **📋 /banned_list** - Список забаненных ⚠️ *Команды работают только в группах и требуют прав администратора* """ await message.answer(help_text, parse_mode=None)