diff --git a/handlers/admin/clusters/clusters_handler.py b/handlers/admin/clusters/clusters_handler.py index 1c153731..9bad11ef 100644 --- a/handlers/admin/clusters/clusters_handler.py +++ b/handlers/admin/clusters/clusters_handler.py @@ -39,6 +39,8 @@ class AdminClusterStates(StatesGroup): waiting_for_server_name = State() waiting_for_subscription_url = State() waiting_for_days_input = State() + waiting_for_new_cluster_name = State() + waiting_for_new_server_name = State() @router.callback_query( @@ -538,3 +540,195 @@ async def handle_days_input(message: Message, state: FSMContext, session: Any): await message.answer("❌ Произошла ошибка при продлении времени.") finally: await state.clear() + +@router.callback_query(AdminClusterCallback.filter(F.action == "rename"), IsAdminFilter()) +async def handle_rename_cluster(callback_query: CallbackQuery, callback_data: AdminClusterCallback, state: FSMContext): + cluster_name = callback_data.data + await state.update_data(old_cluster_name=cluster_name) + + text = ( + f"✏️ Введите новое имя для кластера '{cluster_name}':\n\n" + "▸ Имя должно быть уникальным.\n" + "▸ Имя не должно превышать 12 символов.\n\n" + "📌 Пример: new_cluster" + ) + + await callback_query.message.edit_text( + text=text, + reply_markup=build_admin_back_kb("clusters"), + ) + await state.set_state(AdminClusterStates.waiting_for_new_cluster_name) + + +@router.message(AdminClusterStates.waiting_for_new_cluster_name, IsAdminFilter()) +async def handle_new_cluster_name_input(message: Message, state: FSMContext, session: Any): + if not message.text: + await message.answer( + text="❌ Имя кластера не может быть пустым! Попробуйте снова.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + new_cluster_name = message.text.strip() + if len(new_cluster_name) > 12: + await message.answer( + text="❌ Имя кластера не должно превышать 12 символов! Попробуйте снова.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + user_data = await state.get_data() + old_cluster_name = user_data.get("old_cluster_name") + + conn = await asyncpg.connect(DATABASE_URL) + try: + existing_cluster = await conn.fetchval( + "SELECT cluster_name FROM servers WHERE cluster_name = $1 LIMIT 1", + new_cluster_name + ) + if existing_cluster: + await message.answer( + text=f"❌ Кластер с именем '{new_cluster_name}' уже существует. Введите другое имя.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + keys_count = await conn.fetchval( + "SELECT COUNT(*) FROM keys WHERE server_id = $1", + old_cluster_name + ) + + async with conn.transaction(): + await conn.execute( + "UPDATE servers SET cluster_name = $1 WHERE cluster_name = $2", + new_cluster_name, + old_cluster_name + ) + + if keys_count > 0: + await conn.execute( + "UPDATE keys SET server_id = $1 WHERE server_id = $2", + new_cluster_name, + old_cluster_name + ) + + await message.answer( + text=f"✅ Название кластера успешно изменено с '{old_cluster_name}' на '{new_cluster_name}'!", + reply_markup=build_admin_back_kb("clusters"), + ) + except Exception as e: + logger.error(f"Ошибка при смене имени кластера {old_cluster_name} на {new_cluster_name}: {e}") + await message.answer( + text=f"❌ Произошла ошибка при смене имени кластера: {e}", + reply_markup=build_admin_back_kb("clusters"), + ) + finally: + await conn.close() + await state.clear() + + +@router.callback_query(AdminServerCallback.filter(F.action == "rename"), IsAdminFilter()) +async def handle_rename_server(callback_query: CallbackQuery, callback_data: AdminServerCallback, state: FSMContext): + old_server_name = callback_data.data + + servers = await get_servers() + cluster_name = None + for c_name, server_list in servers.items(): + for server in server_list: + if server["server_name"] == old_server_name: + cluster_name = c_name + break + if cluster_name: + break + + if not cluster_name: + await callback_query.message.edit_text( + text=f"❌ Не удалось найти кластер для сервера '{old_server_name}'.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + await state.update_data(old_server_name=old_server_name, cluster_name=cluster_name) + + text = ( + f"✏️ Введите новое имя для сервера '{old_server_name}' в кластере '{cluster_name}':\n\n" + "▸ Имя должно быть уникальным в пределах кластера.\n" + "▸ Имя не должно превышать 12 символов.\n\n" + "📌 Пример: new_server" + ) + + await callback_query.message.edit_text( + text=text, + reply_markup=build_admin_back_kb("clusters"), + ) + await state.set_state(AdminClusterStates.waiting_for_new_server_name) + + +@router.message(AdminClusterStates.waiting_for_new_server_name, IsAdminFilter()) +async def handle_new_server_name_input(message: Message, state: FSMContext, session: Any): + if not message.text: + await message.answer( + text="❌ Имя сервера не может быть пустым! Попробуйте снова.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + new_server_name = message.text.strip() + if len(new_server_name) > 12: + await message.answer( + text="❌ Имя сервера не должно превышать 12 символов! Попробуйте снова.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + user_data = await state.get_data() + old_server_name = user_data.get("old_server_name") + cluster_name = user_data.get("cluster_name") + + conn = await asyncpg.connect(DATABASE_URL) + try: + existing_server = await conn.fetchval( + "SELECT server_name FROM servers WHERE cluster_name = $1 AND server_name = $2 LIMIT 1", + cluster_name, + new_server_name + ) + if existing_server: + await message.answer( + text=f"❌ Сервер с именем '{new_server_name}' уже существует в кластере '{cluster_name}'. Введите другое имя.", + reply_markup=build_admin_back_kb("clusters"), + ) + return + + keys_count = await conn.fetchval( + "SELECT COUNT(*) FROM keys WHERE server_id = $1", + old_server_name + ) + + async with conn.transaction(): + await conn.execute( + "UPDATE servers SET server_name = $1 WHERE cluster_name = $2 AND server_name = $3", + new_server_name, + cluster_name, + old_server_name + ) + + if keys_count > 0: + await conn.execute( + "UPDATE keys SET server_id = $1 WHERE server_id = $2", + new_server_name, + old_server_name + ) + + await message.answer( + text=f"✅ Название сервера успешно изменено с '{old_server_name}' на '{new_server_name}' в кластере '{cluster_name}'!", + reply_markup=build_admin_back_kb("clusters"), + ) + except Exception as e: + logger.error(f"Ошибка при смене имени сервера {old_server_name} на {new_server_name}: {e}") + await message.answer( + text=f"❌ Произошла ошибка при смене имени сервера: {e}", + reply_markup=build_admin_back_kb("clusters"), + ) + finally: + await conn.close() + await state.clear()