import subprocess from datetime import datetime import asyncpg from aiogram import F, Router, types from aiogram.filters import Command from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.types import ( CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message, ) from aiogram.utils.keyboard import InlineKeyboardBuilder from backup import backup_database from bot import bot from config import ADMIN_ID, DATABASE_URL from handlers.commands import send_message_to_all_clients router = Router() class UserEditorState(StatesGroup): waiting_for_tg_id = State() displaying_user_info = State() @router.message(Command("admin")) async def handle_admin_command(message: types.Message, is_admin: bool): if is_admin: builder = InlineKeyboardBuilder() builder.add( InlineKeyboardButton( text="Статистика пользователей", callback_data="user_stats" ) ) builder.add( InlineKeyboardButton( text="Редактор пользователей", callback_data="user_editor" ) ) builder.add( InlineKeyboardButton( text="Отправить сообщение всем клиентам", callback_data="send_to_alls" ) ) builder.add(InlineKeyboardButton(text="Создать бэкап", callback_data="backups")) builder.add( InlineKeyboardButton(text="Перезапустить бота", callback_data="restart_bot") ) await bot.send_message( message.chat.id, "Панель администратора.", reply_markup=builder.as_markup() ) else: await bot.send_message(message.chat.id, "У вас нет доступа к этой команде.") @router.callback_query(F.data == "user_stats") async def user_stats_menu(callback_query: CallbackQuery, is_admin: bool): if is_admin: conn = await asyncpg.connect(DATABASE_URL) try: total_users = await conn.fetchval("SELECT COUNT(*) FROM connections") total_keys = await conn.fetchval("SELECT COUNT(*) FROM keys") total_referrals = await conn.fetchval("SELECT COUNT(*) FROM referrals") active_keys = await conn.fetchval( "SELECT COUNT(*) FROM keys WHERE expiry_time > $1", int(datetime.utcnow().timestamp() * 1000), ) expired_keys = total_keys - active_keys stats_message = ( f"🔹 Общая статистика пользователей:\n" f"• Всего пользователей: {total_users}\n" f"• Всего ключей: {total_keys}\n" f"• Всего рефералов: {total_referrals}\n" f"• Активные ключи: {active_keys}\n" f"• Истекшие ключи: {expired_keys}" ) builder = InlineKeyboardBuilder() builder.add( InlineKeyboardButton(text="Назад", callback_data="back_to_admin_menu") ) await callback_query.message.edit_text( stats_message, reply_markup=builder.as_markup(), parse_mode="HTML" ) finally: await conn.close() await callback_query.answer() @router.callback_query(F.data == "send_to_alls") async def handle_send_to_all( callback_query: CallbackQuery, state: FSMContext, is_admin: bool ): if is_admin: await send_message_to_all_clients( callback_query.message, state, from_panel=True ) await callback_query.answer() @router.callback_query(F.data == "backups") async def handle_backup(message: Message, is_admin: bool): if is_admin: await message.answer("Запускаю бэкап базы данных...") await backup_database() await message.answer("Бэкап завершен и отправлен админу.") @router.callback_query(F.data == "restart_bot") async def handle_restart(callback_query: CallbackQuery, is_admin: bool): if is_admin: try: result = subprocess.run( ["sudo", "systemctl", "restart", "bot.service"], check=True, capture_output=True, text=True, ) await callback_query.message.answer("Бот успешно перезапущен.") except subprocess.CalledProcessError as e: await callback_query.message.answer( f"Бот будет перезапущен через 30 секунд {e.stderr}" ) @router.callback_query(F.data == "user_editor") async def user_editor_menu(callback_query: CallbackQuery, is_admin: bool): if is_admin: builder = InlineKeyboardBuilder() builder.add( InlineKeyboardButton( text="Поиск по имени ключа", callback_data="search_by_key_name" ) ) builder.add( InlineKeyboardButton(text="Поиск по tg_id", callback_data="search_by_tg_id") ) builder.add( InlineKeyboardButton(text="Назад", callback_data="back_to_admin_menu") ) await callback_query.message.edit_text( "Выберите метод поиска:", reply_markup=builder.as_markup() ) @router.callback_query(F.data == "back_to_admin_menu") async def back_to_admin_menu(callback_query: CallbackQuery, is_admin: bool): try: await callback_query.message.delete() except Exception: pass tg_id = callback_query.from_user.id if is_admin: builder = InlineKeyboardBuilder() builder.add( InlineKeyboardButton( text="Статистика пользователей", callback_data="user_stats" ) ) builder.add( InlineKeyboardButton( text="Редактор пользователей", callback_data="user_editor" ) ) builder.add( InlineKeyboardButton( text="Отправить сообщение всем клиентам", callback_data="send_to_alls", ) ) builder.add(InlineKeyboardButton(text="Создать бэкап", callback_data="backups")) builder.add( InlineKeyboardButton(text="Перезапустить бота", callback_data="restart_bot") ) await bot.send_message( tg_id, "Панель администратора", reply_markup=builder.as_markup() ) async def handle_error(tg_id, callback_query, message): await bot.edit_message_text( message, chat_id=tg_id, message_id=callback_query.message.message_id )