"""Админские обработчики для управления чатом""" from aiogram import Router, F from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton from aiogram.filters import Command from sqlalchemy.ext.asyncio import AsyncSession from src.filters.case_insensitive import CaseInsensitiveCommand from src.core.chat_services import ( ChatSettingsService, BanService, ChatMessageService ) from src.core.services import UserService from src.core.database import async_session_maker from src.core.config import ADMIN_IDS from src.core.permissions import admin_only router = Router(name='admin_chat_router') def get_chat_mode_keyboard() -> InlineKeyboardMarkup: """Клавиатура выбора режима чата""" return InlineKeyboardMarkup(inline_keyboard=[ [ InlineKeyboardButton(text="📢 Рассылка всем", callback_data="chat_mode:broadcast"), InlineKeyboardButton(text="➡️ Пересылка в канал", callback_data="chat_mode:forward") ], [InlineKeyboardButton(text="❌ Закрыть", callback_data="close_menu")] ]) @router.message(CaseInsensitiveCommand("chat_mode")) @admin_only async def cmd_chat_mode(message: Message): """Команда управления режимом чата (регистронезависимо)""" async with async_session_maker() as session: settings = await ChatSettingsService.get_or_create_settings(session) mode_text = "📢 Рассылка всем пользователям" if settings.mode == 'broadcast' else "➡️ Пересылка в канал" await message.answer( f"🎛 Управление режимом чата\n\n" f"Текущий режим: {mode_text}\n\n" f"Выберите режим работы:", reply_markup=get_chat_mode_keyboard(), parse_mode="HTML" ) @router.callback_query(F.data.startswith("chat_mode:")) async def process_chat_mode(callback: CallbackQuery): """Обработка выбора режима чата""" mode = callback.data.split(":")[1] async with async_session_maker() as session: settings = await ChatSettingsService.set_mode(session, mode) mode_text = "📢 Рассылка всем пользователям" if mode == 'broadcast' else "➡️ Пересылка в канал" await callback.message.edit_text( f"✅ Режим чата изменен!\n\n" f"Новый режим: {mode_text}", reply_markup=None ) await callback.answer("✅ Режим изменен") @router.message(CaseInsensitiveCommand("set_forward")) @admin_only async def cmd_set_forward(message: Message): """Установить ID канала для пересылки (регистронезависимо)""" args = message.text.split(maxsplit=1) if len(args) < 2: await message.answer( "📝 Использование:\n" "/set_forward \n\n" "Пример: /set_forward -1001234567890\n\n" "💡 Чтобы узнать ID канала/группы:\n" "1. Добавьте бота в канал/группу\n" "2. Напишите любое сообщение\n" "3. Перешлите его боту @userinfobot", parse_mode="HTML" ) return chat_id = args[1].strip() async with async_session_maker() as session: settings = await ChatSettingsService.set_forward_chat(session, chat_id) await message.answer( f"✅ ID канала для пересылки установлен!\n\n" f"Chat ID: {chat_id}\n\n" f"Теперь переключитесь в режим пересылки командой /chat_mode", parse_mode="HTML" ) @router.message(CaseInsensitiveCommand("global_ban")) @admin_only async def cmd_global_ban(message: Message): """Включить/выключить глобальный бан чата (регистронезависимо)""" async with async_session_maker() as session: settings = await ChatSettingsService.get_or_create_settings(session) # Переключаем состояние new_state = not settings.global_ban settings = await ChatSettingsService.set_global_ban(session, new_state) if new_state: await message.answer( "🔇 Глобальный бан включен\n\n" "Теперь только администраторы могут отправлять сообщения в чат", parse_mode="HTML" ) else: await message.answer( "🔊 Глобальный бан выключен\n\n" "Все пользователи снова могут отправлять сообщения", parse_mode="HTML" ) @router.message(CaseInsensitiveCommand("ban")) @admin_only async def cmd_ban(message: Message): """Забанить пользователя (регистронезависимо)""" # Проверяем является ли это ответом на сообщение if message.reply_to_message: target_user_id = message.reply_to_message.from_user.id reason = message.text.split(maxsplit=1)[1] if len(message.text.split(maxsplit=1)) > 1 else None else: args = message.text.split(maxsplit=2) if len(args) < 2: await message.answer( "📝 Использование:\n\n" "1. Ответьте на сообщение пользователя: /ban [причина]\n" "2. Укажите ID: /ban [причина]\n\n" "Пример: /ban 123456789 Спам", parse_mode="HTML" ) return try: target_user_id = int(args[1]) reason = args[2] if len(args) > 2 else None except ValueError: await message.answer("❌ Неверный ID пользователя") return async with async_session_maker() as session: # Получаем пользователя user = await UserService.get_user_by_telegram_id(session, target_user_id) if not user: await message.answer("❌ Пользователь не найден в базе") return # Получаем админа admin = await UserService.get_or_create_user( session, message.from_user.id, username=message.from_user.username, first_name=message.from_user.first_name, last_name=message.from_user.last_name ) # Баним ban = await BanService.ban_user( session, user_id=user.id, telegram_id=target_user_id, banned_by=admin.id, reason=reason ) reason_text = f"\n📝 Причина: {reason}" if reason else "" await message.answer( f"🚫 Пользователь забанен\n\n" f"👤 Пользователь: {user.name or 'Неизвестен'}\n" f"🆔 ID: {target_user_id}" f"{reason_text}", parse_mode="HTML" ) @router.message(CaseInsensitiveCommand("unban")) @admin_only async def cmd_unban(message: Message): """Разбанить пользователя (регистронезависимо)""" # Проверяем является ли это ответом на сообщение if message.reply_to_message: target_user_id = message.reply_to_message.from_user.id else: args = message.text.split() if len(args) < 2: await message.answer( "📝 Использование:\n\n" "1. Ответьте на сообщение пользователя: /unban\n" "2. Укажите ID: /unban \n\n" "Пример: /unban 123456789", parse_mode="HTML" ) return try: target_user_id = int(args[1]) except ValueError: await message.answer("❌ Неверный ID пользователя") return async with async_session_maker() as session: # Разбаниваем success = await BanService.unban_user(session, target_user_id) if success: await message.answer( f"✅ Пользователь разбанен\n\n" f"🆔 ID: {target_user_id}\n\n" f"Теперь пользователь может отправлять сообщения", parse_mode="HTML" ) else: await message.answer("❌ Пользователь не был забанен") @router.message(CaseInsensitiveCommand("banlist")) @admin_only async def cmd_banlist(message: Message): """Показать список заблокированных пользователей (регистронезависимо)""" async with async_session_maker() as session: banned_users = await BanService.get_banned_users(session, active_only=True) if not banned_users: await message.answer("📋 Список банов пуст") return text = "🚫 Забаненные пользователи\n\n" for ban in banned_users: user = ban.user admin = ban.admin text += f"👤 {user.name or 'Неизвестен'} ({ban.telegram_id})\n" text += f"🔨 Забанил: {admin.name if admin else 'Неизвестен'}\n" if ban.reason: text += f"📝 Причина: {ban.reason}\n" text += f"📅 Дата: {ban.banned_at.strftime('%d.%m.%Y %H:%M')}\n" text += "\n" await message.answer(text, parse_mode="HTML") @router.message(CaseInsensitiveCommand("delete_msg")) @admin_only async def cmd_delete_message(message: Message): """Удалить сообщение из чата (пометить как удаленное) (регистронезависимо)""" if not message.reply_to_message: await message.answer( "📝 Использование:\n\n" "Ответьте на сообщение которое хотите удалить командой /delete_msg", parse_mode="HTML" ) return async with async_session_maker() as session: # Получаем админа admin = await UserService.get_or_create_user( session, message.from_user.id, username=message.from_user.username, first_name=message.from_user.first_name, last_name=message.from_user.last_name ) # Находим сообщение в базе по telegram_message_id from sqlalchemy import select from src.core.models import ChatMessage result = await session.execute( select(ChatMessage).where( ChatMessage.telegram_message_id == message.reply_to_message.message_id ) ) chat_message = result.scalar_one_or_none() if not chat_message: await message.answer("❌ Сообщение не найдено в базе данных") return # Помечаем как удаленное success = await ChatMessageService.delete_message( session, message_id=chat_message.id, deleted_by=admin.id ) if success: # Пытаемся удалить сообщение у всех пользователей if chat_message.forwarded_message_ids: deleted_count = 0 for user_telegram_id, msg_id in chat_message.forwarded_message_ids.items(): try: await message.bot.delete_message(int(user_telegram_id), msg_id) deleted_count += 1 except Exception as e: print(f"Failed to delete message {msg_id} for user {user_telegram_id}: {e}") await message.answer( f"✅ Сообщение удалено\n\n" f"🗑 Удалено у {deleted_count} пользователей", parse_mode="HTML" ) else: await message.answer("✅ Сообщение помечено как удаленное") else: await message.answer("❌ Не удалось удалить сообщение") @router.message(CaseInsensitiveCommand("chat_stats")) @admin_only async def cmd_chat_stats(message: Message): """Статистика чата (регистронезависимо)""" async with async_session_maker() as session: settings = await ChatSettingsService.get_or_create_settings(session) banned_users = await BanService.get_banned_users(session, active_only=True) recent_messages = await ChatMessageService.get_recent_messages(session, limit=100) mode_text = "📢 Рассылка всем" if settings.mode == 'broadcast' else "➡️ Пересылка в канал" global_ban_text = "🔇 Включен" if settings.global_ban else "🔊 Выключен" text = ( f"📊 Статистика чата\n\n" f"🎛 Режим: {mode_text}\n" f"🚫 Глобальный бан: {global_ban_text}\n" f"👥 Забанено пользователей: {len(banned_users)}\n" f"💬 Сообщений за последнее время: {len(recent_messages)}\n" ) if settings.mode == 'forward' and settings.forward_chat_id: text += f"\n➡️ ID канала: {settings.forward_chat_id}" await message.answer(text, parse_mode="HTML") @router.callback_query(F.data == "close_menu") async def close_menu(callback: CallbackQuery): """Закрыть меню""" await callback.message.delete() await callback.answer()