Первый коммит

This commit is contained in:
2026-02-17 11:24:55 +07:00
commit a06448ca4b
109 changed files with 21165 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
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.filters import IsAdmin
from bot.utils import status_clear
from configs import COMMANDS
from database import db
# Настройки роутера
__all__ = ("router",)
from middleware import logger
CMD: str = "ban"
router: Router = Router(name=f"{CMD}_cmd_router")
@router.message(Command(*COMMANDS[CMD], ignore_case=True), IsAdmin())
async def ban_user_cmd(message: Message, state: FSMContext) -> None:
"""
Команда /ban для блокировки пользователей.
Использование: /ban <user_id> или ответ на сообщение пользователя + /ban
"""
await status_clear(update=message, state=state)
try:
# Проверяем есть ли ответ на сообщение
if message.reply_to_message:
# Бан по ответу на сообщение
target_user: User | None = message.reply_to_message.from_user
if not target_user:
await message.answer("Не удалось определить пользователя")
return
target_user_id: int = target_user.id
target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}"
# Проверяем, не пытаемся ли забанить бота
if target_user_id == message.bot.id:
await message.answer("❌ Нельзя заблокировать бота!")
return
# Баним пользователя
success: bool = await _ban_user(target_user_id, target_username, message)
if success:
safe_username: str = escape(target_username)
response_text = f"✅ Пользователь {safe_username} (ID: {target_user_id}) заблокирован!"
# Пытаемся забанить в чате (если команда вызвана в группе/чате)
if message.chat.type in ["group", "supergroup"]:
try:
await message.bot.ban_chat_member(
chat_id=message.chat.id,
user_id=target_user_id
)
response_text += "\n🚫 Пользователь исключен из чата."
except Exception as e:
logger.warning(f"Не удалось исключить пользователя из чата: {e}")
response_text += "\n⚠️ Не удалось исключить пользователя из чата."
await message.answer(
text=response_text,
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"
"• Ответьте на сообщение пользователя командой /ban\n"
"• Или укажите ID: /ban <user_id>"
)
return
try:
target_user_id: int = int(command_parts[1])
# Проверяем, не пытаемся ли забанить бота
if target_user_id == message.bot.id:
await message.answer("❌ Нельзя заблокировать бота!")
return
success: bool = await _ban_user(target_user_id, f"ID{target_user_id}", message)
if success:
response_text = f"✅ Пользователь (ID: {target_user_id}) заблокирован!"
# Пытаемся забанить в чате
if message.chat.type in ["group", "supergroup"]:
try:
await message.bot.ban_chat_member(
chat_id=message.chat.id,
user_id=target_user_id
)
response_text += "\n🚫 Пользователь исключен из чата."
except Exception as e:
logger.warning(f"Не удалось исключить пользователя из чата: {e}")
response_text += "\n⚠️ Не удалось исключить пользователя из чата."
await message.answer(
text=response_text,
parse_mode=None
)
else:
await message.answer("❌ Пользователь не найден или уже заблокирован")
except ValueError:
await message.answer("❌ Неверный формат ID пользователя")
except Exception as e:
logger.error(f"Ошибка в команде /ban: {e}")
await message.answer(
"⚠️ Произошла непредвиденная ошибка при выполнении команды.\n"
"Попробуйте повторить действие позже или нажмите /start"
)
async def _ban_user(user_id: int, username: str, message: Message) -> bool:
"""
Внутренняя функция для блокировки пользователя.
"""
try:
# Сначала проверяем существует ли пользователь
user: User | None = await db.get_user(user_id)
if not user:
# Если пользователя нет - создаем его забаненным
await db.add_user(
user_id=user_id,
username=username,
full_name=username
)
# Баним пользователя
await db.ban_user(user_id)
# Логируем действие
admin_username = message.from_user.username or message.from_user.full_name or f"ID{message.from_user.id}"
logger.info(f"🛑 Админ @{admin_username} заблокировал пользователя @{username} (ID: {user_id})")
return True
except Exception as e:
logger.error(f"❌ Ошибка при блокировке пользователя {user_id}: {e}")
return False
@router.message(Command("unban", ignore_case=True), IsAdmin())
async def unban_user_cmd(message: Message, state: FSMContext) -> None:
"""
Команда /unban для разблокировки пользователей.
"""
await status_clear(update=message, state=state)
try:
if message.reply_to_message:
target_user: User | None = message.reply_to_message.from_user
if not target_user:
await message.answer("Не удалось определить пользователя")
return
target_user_id: int = target_user.id
target_username: str = target_user.username or target_user.full_name or f"ID{target_user_id}"
else:
command_parts: list[str] = message.text.split()
if len(command_parts) < 2:
await message.answer(
" Использование команды:\n"
"• Ответьте на сообщение пользователя командой /unban\n"
"• Или укажите ID: /unban <user_id>"
)
return
try:
target_user_id: int = int(command_parts[1])
target_username: str = f"ID{target_user_id}"
except ValueError:
await message.answer("❌ Неверный формат ID пользователя")
return
# Разбаниваем пользователя
await db.unban_user(target_user_id)
# Логируем действие
admin_username: str = message.from_user.username or message.from_user.full_name or f"ID{message.from_user.id}"
logger.info(f"🔓 Админ @{admin_username} разблокировал пользователя @{target_username} (ID: {target_user_id})")
# Экранируем специальные символы
safe_username: str = escape(target_username)
response_text = f"✅ Пользователь {safe_username} (ID: {target_user_id}) разблокирован!"
# Пытаемся разбанить в чате
if message.chat.type in ["group", "supergroup"]:
try:
await message.bot.unban_chat_member(
chat_id=message.chat.id,
user_id=target_user_id
)
response_text += "\n👥 Пользователь может вернуться в чат."
except Exception as e:
logger.warning(f"Не удалось разблокировать пользователя в чате: {e}")
await message.answer(
text=response_text,
parse_mode=None
)
except Exception as e:
logger.error(f"❌ Ошибка при разблокировке пользователя: {e}")
await message.answer("Не удалось разблокировать пользователя")
@router.message(Command("banned_list", ignore_case=True), IsAdmin())
async def banned_list_cmd(message: Message, state: FSMContext) -> None:
"""
Команда /banned_list для просмотра списка забаненных пользователей.
"""
await status_clear(update=message, state=state)
try:
# Получаем всех пользователей включая забаненных
all_users: list[User] = await db.get_all_users(include_banned=True)
# Фильтруем только забаненных
banned_users: list[User] = [user for user in all_users if getattr(user, 'status', None) == "banned"]
if not banned_users:
await message.answer("📭 Список забаненных пользователей пуст")
return
# Формируем сообщение со списком
banned_list: str = "🚫 Заблокированные пользователи:\n\n"
for user in banned_users[:50]: # Ограничиваем вывод
username: str = f"@{user.username}" if getattr(user, 'username', None) else getattr(user, 'full_name',
'Неизвестно')
# Экранируем специальные символы
safe_username = escape(username)
user_id = getattr(user, 'id', 'N/A')
banned_list += f"{safe_username} (ID: {user_id})\n"
if len(banned_users) > 50:
banned_list += f"\n... и еще {len(banned_users) - 50} пользователей"
await message.answer(banned_list, parse_mode=None)
except Exception as e:
logger.error(f"❌ Ошибка при получении списка забаненных: {e}")
await message.answer("Не удалось получить список забаненных пользователей")