Первый коммит
This commit is contained in:
18
bot/handlers/commands/admins/__init__.py
Normal file
18
bot/handlers/commands/admins/__init__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from aiogram import Router
|
||||
|
||||
#from .ban_cmd import router as ban_cmd_router
|
||||
from .all_cmd import router as all_cmd_router
|
||||
from .pin_cmd import router as pin_cmd_router
|
||||
from .kick_cmd import router as kick_cmd_router
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
router.include_routers(
|
||||
#ban_cmd_router,
|
||||
kick_cmd_router,
|
||||
pin_cmd_router,
|
||||
all_cmd_router,
|
||||
|
||||
)
|
||||
81
bot/handlers/commands/admins/all_cmd.py
Normal file
81
bot/handlers/commands/admins/all_cmd.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from asyncio import create_task
|
||||
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message
|
||||
from aiogram.exceptions import TelegramBadRequest
|
||||
from aiogram.fsm.context import FSMContext
|
||||
|
||||
from bot.core.bots import bot, BotInfo
|
||||
from bot.filters import IsOwner
|
||||
from bot.utils import status_clear, auto_delete_message, hidden_admins_message
|
||||
from configs import COMMANDS
|
||||
from middleware.loggers import logger
|
||||
|
||||
__all__ = ("router",)
|
||||
|
||||
# Ключ для команды
|
||||
CMD: str = "all"
|
||||
# Инициализация роутера
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
|
||||
|
||||
@router.message(
|
||||
F.text.lower().regexp(rf"^({'|'.join(COMMANDS[CMD])})\s?.*"), # ловим текст без префикса
|
||||
F.chat.type.in_({"supergroup", "group"}),
|
||||
IsOwner()
|
||||
)
|
||||
@router.message(
|
||||
Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True),
|
||||
F.chat.type.in_({"supergroup", "group"}),
|
||||
IsOwner()
|
||||
)
|
||||
async def notify_all_text(message: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Обработчик команды /all, /call и текстовых эквивалентов типа "Калл Привет всем".
|
||||
|
||||
Функционал:
|
||||
1. Считывает весь текст после команды.
|
||||
2. Формирует скрытое сообщение для администраторов.
|
||||
3. Отправляет сообщение в чат.
|
||||
4. Автоматически удаляет сообщение через неделю.
|
||||
5. Пытается закрепить сообщение в чате.
|
||||
|
||||
Args:
|
||||
message (Message): Объект входящего сообщения.
|
||||
state (FSMContext): Контекст FSM, используется для очистки состояния.
|
||||
"""
|
||||
# Очистка состояния FSM перед выполнением команды
|
||||
await status_clear(update=message, state=state)
|
||||
|
||||
# Извлечение текста после команды
|
||||
parts: list[str] = message.text.split(" ", 1)
|
||||
custom_text: str = parts[1] if len(parts) > 1 else "⚡ Внимание всем!"
|
||||
|
||||
# Формирование скрытого текста для администраторов
|
||||
hidden_text: str = await hidden_admins_message(message=message, text=custom_text)
|
||||
|
||||
# Отправка сообщения в чат
|
||||
sent_message: Message = await message.answer(hidden_text)
|
||||
|
||||
# Запуск асинхронной задачи по удалению сообщения через 7 дней
|
||||
create_task(
|
||||
auto_delete_message(
|
||||
chat_id=message.chat.id,
|
||||
message_id=sent_message.message_id,
|
||||
delay=604800 # 7 дней в секундах
|
||||
)
|
||||
)
|
||||
|
||||
# Попытка закрепить сообщение и удалить "системное" сообщение о закреплении
|
||||
try:
|
||||
await bot.pin_chat_message(
|
||||
chat_id=message.chat.id,
|
||||
message_id=sent_message.message_id,
|
||||
disable_notification=False
|
||||
)
|
||||
# Иногда Telegram создает дополнительное уведомление при закреплении
|
||||
await bot.delete_message(chat_id=message.chat.id, message_id=sent_message.message_id + 1)
|
||||
logger.debug(f"[ALL] Сообщение закреплено: {custom_text}")
|
||||
except TelegramBadRequest as e:
|
||||
logger.error(f"[ALL] Ошибка закрепления сообщения: {e}")
|
||||
258
bot/handlers/commands/admins/ban_cmd.py
Normal file
258
bot/handlers/commands/admins/ban_cmd.py
Normal 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("❌ Не удалось получить список забаненных пользователей")
|
||||
277
bot/handlers/commands/admins/kick_cmd.py
Normal file
277
bot/handlers/commands/admins/kick_cmd.py
Normal file
@@ -0,0 +1,277 @@
|
||||
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(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 <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(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 <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(update=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)
|
||||
77
bot/handlers/commands/admins/pin_cmd.py
Normal file
77
bot/handlers/commands/admins/pin_cmd.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from asyncio import create_task
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from bot.core.bots import BotInfo, bot
|
||||
from bot.filters import IsOwner
|
||||
from bot.templates import msg
|
||||
from bot.utils import status_clear
|
||||
from bot.utils.auto_delete import auto_delete_message
|
||||
from configs import COMMANDS
|
||||
|
||||
__all__ = ("router",)
|
||||
CMD: str = "pin".lower()
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
|
||||
|
||||
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True), IsOwner())
|
||||
async def pin_cmd(message: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Обработчик команды /pin для закрепления последнего сообщения или ответа.
|
||||
"""
|
||||
# Если есть reply → закрепляем его, иначе закрепляем предыдущее сообщение
|
||||
if message.reply_to_message:
|
||||
target_message_id = message.reply_to_message.message_id
|
||||
else:
|
||||
# Закрепляем предыдущее сообщение (команда - 1)
|
||||
target_message_id = message.message_id - 1
|
||||
|
||||
try:
|
||||
await bot.pin_chat_message(
|
||||
chat_id=message.chat.id,
|
||||
message_id=target_message_id,
|
||||
disable_notification=False
|
||||
)
|
||||
|
||||
# Автоудаление через 7 суток (удаляем закрепленное сообщение)
|
||||
create_task(
|
||||
auto_delete_message(
|
||||
chat_id=message.chat.id,
|
||||
message_id=target_message_id,
|
||||
delay=604800
|
||||
)
|
||||
)
|
||||
|
||||
await msg(update=message, text="✅ Сообщение успешно закреплено", state=state)
|
||||
|
||||
except Exception as e:
|
||||
await msg(update=message, text=f"❌ Ошибка закрепления: {e}", state=state)
|
||||
|
||||
|
||||
@router.callback_query(F.data.casefold().isin(COMMANDS[CMD]), IsOwner())
|
||||
async def pin_callback(callback: CallbackQuery, state: FSMContext) -> None:
|
||||
"""
|
||||
Обработчик кнопки с callback_data="pin".
|
||||
"""
|
||||
await status_clear(update=callback.message, state=state)
|
||||
|
||||
try:
|
||||
await bot.pin_chat_message(
|
||||
chat_id=callback.message.chat.id,
|
||||
message_id=callback.message.message_id,
|
||||
disable_notification=False
|
||||
)
|
||||
|
||||
create_task(
|
||||
auto_delete_message(
|
||||
chat_id=callback.message.chat.id,
|
||||
message_id=callback.message.message_id,
|
||||
delay=604800
|
||||
)
|
||||
)
|
||||
|
||||
await callback.answer("✅ Сообщение закреплено")
|
||||
|
||||
except Exception as e:
|
||||
await callback.answer(f"❌ Ошибка: {e}", show_alert=True)
|
||||
51
bot/handlers/commands/admins/settings_cmd.py
Normal file
51
bot/handlers/commands/admins/settings_cmd.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from aiogram.utils.i18n import gettext as _
|
||||
|
||||
from bot.templates import msg_photo
|
||||
from bot.utils.interesting_facts import interesting_fact
|
||||
from bot.core.bots import BotInfo
|
||||
from configs import COMMANDS, RpValue
|
||||
|
||||
# Настройки экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
CMD: str = "settings".lower()
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
|
||||
|
||||
@router.callback_query(F.data.lower() == CMD)
|
||||
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True))
|
||||
async def start_cmd(message: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""Обработчик команды /start"""
|
||||
await state.clear()
|
||||
|
||||
# Создание инлайн-клавиатуры
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(InlineKeyboardButton(text="Инфо-канал🗂", url=CustomConfig.INFO_URL))
|
||||
ikb.row(InlineKeyboardButton(text="Вступление🚀", callback_data='new'),
|
||||
InlineKeyboardButton(text="Анкета📖", callback_data='anketa'))
|
||||
ikb.row(InlineKeyboardButton(text="Связь с администрацией🌐", callback_data='admin'))
|
||||
|
||||
# Формируем приветственное сообщение
|
||||
text: str = _(
|
||||
"""Добро пожаловать, <a href="{url}">{name}</a>!
|
||||
|
||||
Я ваш искусственный помощник по ролевой - <b>{rp_name}</b>!
|
||||
Моя цель — помочь вам сориентироваться и сделать ваше вступление куда проще!
|
||||
Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на клавиатуре!
|
||||
|
||||
Интересный факт:
|
||||
<blockquote>{fact}</blockquote>
|
||||
"""
|
||||
).format(
|
||||
url=message.from_user.url if message.from_user else "",
|
||||
name=message.from_user.first_name if message.from_user else "пользователь",
|
||||
rp_name=RpValue.RP_NAME,
|
||||
fact=interesting_fact(),
|
||||
)
|
||||
|
||||
# Отправляем сообщение
|
||||
await msg_photo(update=message, text=text, file=f'assets/{CMD}.jpg', markup=ikb)
|
||||
Reference in New Issue
Block a user