Files
balance_bot/bot/handlers/commands/admins/kick_cmd.py
2026-01-23 04:45:55 +07:00

279 lines
13 KiB
Python
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.
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 <user_id> или ответ на сообщение пользователя + /kick
"""
await status_clear(message=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}) кикнут из чата!",
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\n"
"• Или укажите ID: /kick <user_id>"
)
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 <user_id> или ответ на сообщение пользователя + /kick_ban
"""
await status_clear(message=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 <user_id>"
)
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(message=message, state=state)
help_text = """
🤖 **Команды модерации:**
**👢 /kick** - Кикнуть пользователя (может вернуться по приглашению)
• Ответьте на сообщение пользователя с командой /kick
• Или используйте: /kick <user_id>
**💥 /kick_ban** - Кикнуть пользователя с удалением сообщений
• Ответьте на сообщение пользователя с командой /kick_ban
• Или используйте: /kick_ban <user_id>
**🚫 /ban** - Полностью забанить пользователя
**🔓 /unban** - Разбанить пользователя
**📋 /banned_list** - Список забаненных
⚠️ *Команды работают только в группах и требуют прав администратора*
"""
await message.answer(help_text, parse_mode=None)