remnawave in country_mode/save shortid/bug fixes
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any
|
||||
|
||||
import asyncpg
|
||||
@@ -10,14 +11,27 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from py3xui import AsyncApi
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from backup import create_backup_and_send_to_admins
|
||||
from config import ADMIN_PASSWORD, ADMIN_USERNAME, DATABASE_URL, TOTAL_GB, USE_COUNTRY_SELECTION, REMNAWAVE_PASSWORD, REMNAWAVE_LOGIN
|
||||
from config import (
|
||||
ADMIN_PASSWORD,
|
||||
ADMIN_USERNAME,
|
||||
DATABASE_URL,
|
||||
REMNAWAVE_LOGIN,
|
||||
REMNAWAVE_PASSWORD,
|
||||
TOTAL_GB,
|
||||
USE_COUNTRY_SELECTION,
|
||||
)
|
||||
from database import check_unique_server_name, get_servers, update_key_expiry
|
||||
from filters.admin import IsAdminFilter
|
||||
from handlers.keys.key_utils import create_client_on_server, create_key_on_cluster, renew_key_in_cluster, delete_key_from_cluster
|
||||
from handlers.keys.key_utils import (
|
||||
create_client_on_server,
|
||||
create_key_on_cluster,
|
||||
delete_key_from_cluster,
|
||||
renew_key_in_cluster,
|
||||
)
|
||||
from logger import logger
|
||||
from panels.remnawave import RemnawaveAPI
|
||||
|
||||
from ..panel.keyboard import AdminPanelCallback, build_admin_back_kb
|
||||
from .keyboard import (
|
||||
@@ -26,10 +40,9 @@ from .keyboard import (
|
||||
build_cluster_management_kb,
|
||||
build_clusters_editor_kb,
|
||||
build_manage_cluster_kb,
|
||||
build_panel_type_kb,
|
||||
build_sync_cluster_kb,
|
||||
build_panel_type_kb
|
||||
)
|
||||
from panels.remnawave import RemnawaveAPI
|
||||
|
||||
|
||||
router = Router()
|
||||
@@ -194,7 +207,7 @@ async def handle_subscription_url_input(message: Message, state: FSMContext):
|
||||
|
||||
await message.answer(
|
||||
text=f"<b>Введите inbound_id для сервера {server_name} в кластере {cluster_name}:</b>\n\n"
|
||||
f"Для Remnawave это UUID Инбаунда, для 3x-ui — просто ID (например, <code>1</code>).",
|
||||
f"Для Remnawave это UUID Инбаунда, для 3x-ui — просто ID (например, <code>1</code>).",
|
||||
reply_markup=build_admin_back_kb("clusters"),
|
||||
)
|
||||
await state.set_state(AdminClusterStates.waiting_for_inbound_id)
|
||||
@@ -216,7 +229,9 @@ async def handle_inbound_id_input(message: Message, state: FSMContext):
|
||||
|
||||
|
||||
@router.callback_query(AdminClusterCallback.filter(F.action.in_(["panel_3xui", "panel_remnawave"])), IsAdminFilter())
|
||||
async def handle_panel_type_selection(callback_query: CallbackQuery, callback_data: AdminClusterCallback, state: FSMContext):
|
||||
async def handle_panel_type_selection(
|
||||
callback_query: CallbackQuery, callback_data: AdminClusterCallback, state: FSMContext
|
||||
):
|
||||
panel_type = "3x-ui" if callback_data.action == "panel_3xui" else "remnawave"
|
||||
|
||||
user_data = await state.get_data()
|
||||
@@ -437,7 +452,7 @@ async def handle_sync_cluster(callback_query: types.CallbackQuery, callback_data
|
||||
|
||||
try:
|
||||
query_keys = """
|
||||
SELECT tg_id, client_id, email, expiry_time
|
||||
SELECT tg_id, client_id, email, expiry_time, remnawave_link
|
||||
FROM keys
|
||||
WHERE server_id = $1
|
||||
"""
|
||||
@@ -458,18 +473,17 @@ async def handle_sync_cluster(callback_query: types.CallbackQuery, callback_data
|
||||
await delete_key_from_cluster(cluster_name, key["email"], key["client_id"])
|
||||
|
||||
await session.execute(
|
||||
"DELETE FROM keys WHERE tg_id = $1 AND client_id = $2",
|
||||
key["tg_id"],
|
||||
key["client_id"]
|
||||
"DELETE FROM keys WHERE tg_id = $1 AND client_id = $2", key["tg_id"], key["client_id"]
|
||||
)
|
||||
|
||||
result = await create_key_on_cluster(
|
||||
await create_key_on_cluster(
|
||||
cluster_name,
|
||||
key["tg_id"],
|
||||
key["client_id"],
|
||||
key["email"],
|
||||
key["expiry_time"],
|
||||
session=session,
|
||||
remnawave_link=key.get("remnawave_link"),
|
||||
)
|
||||
|
||||
await asyncio.sleep(0.5)
|
||||
@@ -477,7 +491,6 @@ async def handle_sync_cluster(callback_query: types.CallbackQuery, callback_data
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при синхронизации ключа {key['client_id']} в {cluster_name}: {e}")
|
||||
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
text=f"✅ Ключи успешно синхронизированы для кластера {cluster_name}",
|
||||
reply_markup=build_admin_back_kb("clusters"),
|
||||
@@ -622,8 +635,7 @@ async def handle_new_cluster_name_input(message: Message, state: FSMContext, ses
|
||||
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
|
||||
"SELECT cluster_name FROM servers WHERE cluster_name = $1 LIMIT 1", new_cluster_name
|
||||
)
|
||||
if existing_cluster:
|
||||
await message.answer(
|
||||
@@ -632,23 +644,16 @@ async def handle_new_cluster_name_input(message: Message, state: FSMContext, ses
|
||||
)
|
||||
return
|
||||
|
||||
keys_count = await conn.fetchval(
|
||||
"SELECT COUNT(*) FROM keys WHERE server_id = $1",
|
||||
old_cluster_name
|
||||
)
|
||||
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
|
||||
"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
|
||||
"UPDATE keys SET server_id = $1 WHERE server_id = $2", new_cluster_name, old_cluster_name
|
||||
)
|
||||
|
||||
await message.answer(
|
||||
@@ -729,7 +734,7 @@ async def handle_new_server_name_input(message: Message, state: FSMContext, sess
|
||||
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
|
||||
new_server_name,
|
||||
)
|
||||
if existing_server:
|
||||
await message.answer(
|
||||
@@ -738,24 +743,19 @@ async def handle_new_server_name_input(message: Message, state: FSMContext, sess
|
||||
)
|
||||
return
|
||||
|
||||
keys_count = await conn.fetchval(
|
||||
"SELECT COUNT(*) FROM keys WHERE server_id = $1",
|
||||
old_server_name
|
||||
)
|
||||
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
|
||||
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
|
||||
"UPDATE keys SET server_id = $1 WHERE server_id = $2", new_server_name, old_server_name
|
||||
)
|
||||
|
||||
final_text = f"✅ Название сервера успешно изменено с '{old_server_name}' на '{new_server_name}' в кластере '{cluster_name}'!"
|
||||
@@ -787,20 +787,14 @@ async def handle_server_transfer(callback_query: CallbackQuery, state: FSMContex
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
async with conn.transaction():
|
||||
await conn.execute(
|
||||
"UPDATE keys SET server_id = $1 WHERE server_id = $2",
|
||||
new_server_name,
|
||||
old_server_name
|
||||
)
|
||||
await conn.execute("UPDATE keys SET server_id = $1 WHERE server_id = $2", new_server_name, old_server_name)
|
||||
|
||||
await conn.execute(
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2",
|
||||
cluster_name,
|
||||
old_server_name
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2", cluster_name, old_server_name
|
||||
)
|
||||
|
||||
base_text = f"✅ Ключи успешно перенесены на сервер '{new_server_name}', сервер '{old_server_name}' удален!"
|
||||
sync_reminder = "\n\n⚠️ Не забудьте сделать \"Синхронизацию\"."
|
||||
sync_reminder = '\n\n⚠️ Не забудьте сделать "Синхронизацию".'
|
||||
final_text = base_text + (sync_reminder if USE_COUNTRY_SELECTION else "")
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
@@ -831,21 +825,13 @@ async def handle_cluster_transfer(callback_query: CallbackQuery, state: FSMConte
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
try:
|
||||
async with conn.transaction():
|
||||
await conn.execute("UPDATE keys SET server_id = $1 WHERE server_id = $2", new_cluster_name, old_server_name)
|
||||
await conn.execute(
|
||||
"UPDATE keys SET server_id = $1 WHERE server_id = $2",
|
||||
new_cluster_name,
|
||||
old_server_name
|
||||
)
|
||||
await conn.execute(
|
||||
"UPDATE keys SET server_id = $1 WHERE server_id = $2",
|
||||
new_cluster_name,
|
||||
old_cluster_name
|
||||
"UPDATE keys SET server_id = $1 WHERE server_id = $2", new_cluster_name, old_cluster_name
|
||||
)
|
||||
|
||||
await conn.execute(
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2",
|
||||
cluster_name,
|
||||
old_server_name
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2", cluster_name, old_server_name
|
||||
)
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from aiogram.filters.callback_data import CallbackData
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
@@ -134,13 +132,7 @@ def build_sync_cluster_kb(cluster_servers: list, cluster_name: str) -> InlineKey
|
||||
|
||||
def build_panel_type_kb() -> InlineKeyboardMarkup:
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.button(
|
||||
text="🌐 3X-UI",
|
||||
callback_data=AdminClusterCallback(action="panel_3xui").pack()
|
||||
)
|
||||
builder.button(
|
||||
text="🌀 Remnawave",
|
||||
callback_data=AdminClusterCallback(action="panel_remnawave").pack()
|
||||
)
|
||||
builder.button(text="🌐 3X-UI", callback_data=AdminClusterCallback(action="panel_3xui").pack())
|
||||
builder.button(text="🌀 Remnawave", callback_data=AdminClusterCallback(action="panel_remnawave").pack())
|
||||
builder.row(build_admin_back_btn("clusters"))
|
||||
return builder.as_markup()
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from datetime import datetime
|
||||
import html
|
||||
import pytz
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
import pytz
|
||||
|
||||
from aiogram import F, Router
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.fsm.context import FSMContext
|
||||
@@ -217,18 +219,15 @@ async def handle_coupon_delete(callback_query: CallbackQuery, callback_data: Adm
|
||||
coupon_code = callback_data.coupon_code
|
||||
kb = InlineKeyboardBuilder()
|
||||
kb.button(
|
||||
text="✅ Да, удалить",
|
||||
callback_data=AdminCouponDeleteCallback(coupon_code=coupon_code, confirm=True).pack()
|
||||
text="✅ Да, удалить", callback_data=AdminCouponDeleteCallback(coupon_code=coupon_code, confirm=True).pack()
|
||||
)
|
||||
kb.button(
|
||||
text="❌ Нет, отменить",
|
||||
callback_data=AdminCouponDeleteCallback(coupon_code=coupon_code, confirm=False).pack()
|
||||
text="❌ Нет, отменить", callback_data=AdminCouponDeleteCallback(coupon_code=coupon_code, confirm=False).pack()
|
||||
)
|
||||
kb.adjust(1)
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
f"Вы уверены, что хотите удалить купон <b>{coupon_code}</b>?",
|
||||
reply_markup=kb.as_markup()
|
||||
f"Вы уверены, что хотите удалить купон <b>{coupon_code}</b>?", reply_markup=kb.as_markup()
|
||||
)
|
||||
|
||||
|
||||
@@ -242,15 +241,13 @@ async def confirm_coupon_delete(callback_query: CallbackQuery, callback_data: Ad
|
||||
result = await delete_coupon(coupon_code, session)
|
||||
if not result:
|
||||
await callback_query.message.edit_text(
|
||||
f"❌ Купон с кодом {coupon_code} не найден.",
|
||||
reply_markup=build_admin_back_kb("coupons")
|
||||
f"❌ Купон с кодом {coupon_code} не найден.", reply_markup=build_admin_back_kb("coupons")
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при удалении купона: {e}")
|
||||
await callback_query.message.edit_text(
|
||||
"Произошла ошибка при удалении купона.",
|
||||
reply_markup=build_admin_back_kb("coupons")
|
||||
"Произошла ошибка при удалении купона.", reply_markup=build_admin_back_kb("coupons")
|
||||
)
|
||||
return
|
||||
|
||||
@@ -295,7 +292,11 @@ async def inline_coupon_handler(inline_query: InlineQuery, session: Any):
|
||||
return
|
||||
|
||||
title = f"Купон {coupon['code']}"
|
||||
description = f"Получи {coupon['amount']} рублей!" if coupon["amount"] > 0 else f"Продли подписку на {format_days(coupon['days'])}!"
|
||||
description = (
|
||||
f"Получи {coupon['amount']} рублей!"
|
||||
if coupon["amount"] > 0
|
||||
else f"Продли подписку на {format_days(coupon['days'])}!"
|
||||
)
|
||||
message_text = (
|
||||
f"🎫 <b>Купон:</b> {coupon['code']}\n"
|
||||
f"{'💰 <b>Бонус:</b> ' + str(coupon['amount']) + ' рублей' if coupon['amount'] > 0 else '⏳ <b>Продление:</b> ' + format_days(coupon['days'])}\n"
|
||||
@@ -309,15 +310,8 @@ async def inline_coupon_handler(inline_query: InlineQuery, session: Any):
|
||||
id=coupon_code,
|
||||
title=title,
|
||||
description=description,
|
||||
input_message_content=InputTextMessageContent(
|
||||
message_text=message_text,
|
||||
parse_mode=ParseMode.HTML
|
||||
),
|
||||
input_message_content=InputTextMessageContent(message_text=message_text, parse_mode=ParseMode.HTML),
|
||||
reply_markup=builder.as_markup(),
|
||||
)
|
||||
|
||||
await inline_query.answer(
|
||||
results=[result],
|
||||
cache_time=86400,
|
||||
is_personal=True
|
||||
)
|
||||
await inline_query.answer(results=[result], cache_time=86400, is_personal=True)
|
||||
|
||||
@@ -12,7 +12,7 @@ from ..panel.keyboard import AdminPanelCallback, build_admin_back_btn
|
||||
|
||||
class AdminCouponDeleteCallback(CallbackData, prefix="admin_coupon_delete"):
|
||||
coupon_code: str
|
||||
confirm: Optional[bool] = None
|
||||
confirm: bool | None = None
|
||||
|
||||
|
||||
def build_coupons_kb() -> InlineKeyboardMarkup:
|
||||
@@ -59,7 +59,11 @@ def build_coupons_list_kb(coupons: list, current_page: int, total_pages: int) ->
|
||||
def format_coupons_list(coupons: list, username_bot: str) -> str:
|
||||
coupon_list = "📜 Список всех купонов:\n\n"
|
||||
for coupon in coupons:
|
||||
value_text = f"💰 <b>Сумма:</b> {coupon['amount']} рублей" if coupon["amount"] > 0 else f"⏳ <b>{format_days(coupon['days'])}</b>"
|
||||
value_text = (
|
||||
f"💰 <b>Сумма:</b> {coupon['amount']} рублей"
|
||||
if coupon["amount"] > 0
|
||||
else f"⏳ <b>{format_days(coupon['days'])}</b>"
|
||||
)
|
||||
coupon_list += (
|
||||
f"🏷️ <b>Код:</b> {coupon['code']}\n"
|
||||
f"{value_text}\n"
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
from aiogram import F, Router
|
||||
from aiogram.exceptions import TelegramBadRequest
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from aiogram.exceptions import TelegramBadRequest
|
||||
|
||||
from bot import version
|
||||
from filters.admin import IsAdminFilter
|
||||
from logger import logger
|
||||
|
||||
from .keyboard import AdminPanelCallback, build_panel_kb
|
||||
|
||||
from logger import logger
|
||||
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ def build_manage_server_kb(server_name: str, cluster_name: str) -> InlineKeyboar
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.button(text="🗑️ Удалить", callback_data=AdminServerCallback(action="delete", data=server_name).pack())
|
||||
builder.button(text="✏️ Сменить название", callback_data=AdminServerCallback(action="rename", data=server_name).pack())
|
||||
builder.button(
|
||||
text="✏️ Сменить название", callback_data=AdminServerCallback(action="rename", data=server_name).pack()
|
||||
)
|
||||
builder.button(text=BACK, callback_data=AdminClusterCallback(action="manage", data=cluster_name).pack())
|
||||
builder.adjust(1)
|
||||
return builder.as_markup()
|
||||
|
||||
@@ -4,10 +4,10 @@ from aiogram import F, Router, types
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from handlers.buttons import BACK
|
||||
|
||||
from database import delete_server, get_servers
|
||||
from filters.admin import IsAdminFilter
|
||||
from handlers.buttons import BACK
|
||||
|
||||
from ..panel.keyboard import build_admin_back_kb
|
||||
from .keyboard import (
|
||||
@@ -73,10 +73,7 @@ async def process_callback_delete_server(
|
||||
)
|
||||
return
|
||||
|
||||
keys_count = await session.fetchval(
|
||||
"SELECT COUNT(*) FROM keys WHERE server_id = $1",
|
||||
server_name
|
||||
)
|
||||
keys_count = await session.fetchval("SELECT COUNT(*) FROM keys WHERE server_id = $1", server_name)
|
||||
|
||||
if keys_count > 0:
|
||||
await state.update_data(server_name=server_name, cluster_name=cluster_name)
|
||||
@@ -87,7 +84,7 @@ async def process_callback_delete_server(
|
||||
FROM servers
|
||||
WHERE server_name != $1
|
||||
""",
|
||||
server_name
|
||||
server_name,
|
||||
)
|
||||
|
||||
if all_servers:
|
||||
@@ -96,13 +93,12 @@ async def process_callback_delete_server(
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=f"{server['server_name']} ({server['key_count']})",
|
||||
callback_data=f"transfer_to_server|{server['server_name']}|{server_name}"
|
||||
callback_data=f"transfer_to_server|{server['server_name']}|{server_name}",
|
||||
)
|
||||
)
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=BACK,
|
||||
callback_data=AdminServerCallback(action="manage", data=server_name).pack()
|
||||
text=BACK, callback_data=AdminServerCallback(action="manage", data=server_name).pack()
|
||||
)
|
||||
)
|
||||
|
||||
@@ -114,22 +110,16 @@ async def process_callback_delete_server(
|
||||
return
|
||||
|
||||
remaining_servers = await session.fetchval(
|
||||
"SELECT COUNT(*) FROM servers WHERE cluster_name = $1 AND server_name != $2",
|
||||
cluster_name,
|
||||
server_name
|
||||
"SELECT COUNT(*) FROM servers WHERE cluster_name = $1 AND server_name != $2", cluster_name, server_name
|
||||
)
|
||||
|
||||
if remaining_servers == 0:
|
||||
other_clusters = await session.fetch(
|
||||
"SELECT DISTINCT cluster_name FROM servers WHERE cluster_name != $1",
|
||||
cluster_name
|
||||
"SELECT DISTINCT cluster_name FROM servers WHERE cluster_name != $1", cluster_name
|
||||
)
|
||||
|
||||
if other_clusters:
|
||||
cluster_keys_count = await session.fetchval(
|
||||
"SELECT COUNT(*) FROM keys WHERE server_id = $1",
|
||||
cluster_name
|
||||
)
|
||||
cluster_keys_count = await session.fetchval("SELECT COUNT(*) FROM keys WHERE server_id = $1", cluster_name)
|
||||
|
||||
if cluster_keys_count > 0:
|
||||
await state.update_data(server_name=server_name, cluster_name=cluster_name)
|
||||
@@ -141,7 +131,7 @@ async def process_callback_delete_server(
|
||||
WHERE cluster_name != $1
|
||||
GROUP BY cluster_name
|
||||
""",
|
||||
cluster_name
|
||||
cluster_name,
|
||||
)
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
@@ -149,13 +139,12 @@ async def process_callback_delete_server(
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=f"{cluster['cluster_name']} ({cluster['key_count']})",
|
||||
callback_data=f"transfer_to_cluster|{cluster['cluster_name']}|{cluster_name}|{server_name}"
|
||||
callback_data=f"transfer_to_cluster|{cluster['cluster_name']}|{cluster_name}|{server_name}",
|
||||
)
|
||||
)
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=BACK,
|
||||
callback_data=AdminServerCallback(action="manage", data=server_name).pack()
|
||||
text=BACK, callback_data=AdminServerCallback(action="manage", data=server_name).pack()
|
||||
)
|
||||
)
|
||||
|
||||
@@ -167,9 +156,7 @@ async def process_callback_delete_server(
|
||||
return
|
||||
|
||||
await session.execute(
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2",
|
||||
cluster_name,
|
||||
server_name
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2", cluster_name, server_name
|
||||
)
|
||||
await callback_query.message.edit_text(
|
||||
text=f"✅ Сервер '{server_name}' удален. Кластер '{cluster_name}' также удален, так как в нем не осталось серверов.",
|
||||
@@ -177,9 +164,7 @@ async def process_callback_delete_server(
|
||||
)
|
||||
else:
|
||||
await session.execute(
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2",
|
||||
cluster_name,
|
||||
server_name
|
||||
"DELETE FROM servers WHERE cluster_name = $1 AND server_name = $2", cluster_name, server_name
|
||||
)
|
||||
await callback_query.message.edit_text(
|
||||
text=f"✅ Сервер '{server_name}' удален.",
|
||||
|
||||
@@ -826,7 +826,9 @@ async def handle_users_export_referrals(
|
||||
|
||||
|
||||
@router.callback_query(AdminUserEditorCallback.filter(F.action == "users_create_key"), IsAdminFilter())
|
||||
async def handle_create_key_start(callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, state: FSMContext, session: Any):
|
||||
async def handle_create_key_start(
|
||||
callback_query: CallbackQuery, callback_data: AdminUserEditorCallback, state: FSMContext, session: Any
|
||||
):
|
||||
tg_id = callback_data.tg_id
|
||||
await state.update_data(tg_id=tg_id)
|
||||
|
||||
@@ -838,8 +840,7 @@ async def handle_create_key_start(callback_query: CallbackQuery, callback_data:
|
||||
|
||||
if not countries:
|
||||
await callback_query.message.edit_text(
|
||||
"❌ Нет доступных стран для создания ключа.",
|
||||
reply_markup=build_editor_kb(tg_id)
|
||||
"❌ Нет доступных стран для создания ключа.", reply_markup=build_editor_kb(tg_id)
|
||||
)
|
||||
return
|
||||
|
||||
@@ -850,8 +851,7 @@ async def handle_create_key_start(callback_query: CallbackQuery, callback_data:
|
||||
builder.row(build_admin_back_btn())
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
"🌍 <b>Выберите страну для создания ключа:</b>",
|
||||
reply_markup=builder.as_markup()
|
||||
"🌍 <b>Выберите страну для создания ключа:</b>", reply_markup=builder.as_markup()
|
||||
)
|
||||
return
|
||||
|
||||
@@ -862,8 +862,7 @@ async def handle_create_key_start(callback_query: CallbackQuery, callback_data:
|
||||
|
||||
if not cluster_names:
|
||||
await callback_query.message.edit_text(
|
||||
"❌ Нет доступных кластеров для создания ключа.",
|
||||
reply_markup=build_editor_kb(tg_id)
|
||||
"❌ Нет доступных кластеров для создания ключа.", reply_markup=build_editor_kb(tg_id)
|
||||
)
|
||||
return
|
||||
|
||||
@@ -873,8 +872,7 @@ async def handle_create_key_start(callback_query: CallbackQuery, callback_data:
|
||||
builder.row(build_admin_back_btn())
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
"🌐 <b>Выберите кластер для создания ключа:</b>",
|
||||
reply_markup=builder.as_markup()
|
||||
"🌐 <b>Выберите кластер для создания ключа:</b>", reply_markup=builder.as_markup()
|
||||
)
|
||||
|
||||
|
||||
@@ -891,8 +889,7 @@ async def handle_create_key_country(callback_query: CallbackQuery, state: FSMCon
|
||||
builder.row(build_admin_back_btn())
|
||||
|
||||
await callback_query.message.edit_text(
|
||||
text=f"🕒 <b>Выберите срок действия ключа для страны {country}:</b>",
|
||||
reply_markup=builder.as_markup()
|
||||
text=f"🕒 <b>Выберите срок действия ключа для страны {country}:</b>", reply_markup=builder.as_markup()
|
||||
)
|
||||
|
||||
|
||||
@@ -928,15 +925,7 @@ async def handle_create_key_duration(callback_query: CallbackQuery, state: FSMCo
|
||||
|
||||
if USE_COUNTRY_SELECTION and "country" in data:
|
||||
country = data["country"]
|
||||
await create_key_on_cluster(
|
||||
country,
|
||||
tg_id,
|
||||
client_id,
|
||||
email,
|
||||
expiry_ms,
|
||||
plan=months,
|
||||
session=session
|
||||
)
|
||||
await create_key_on_cluster(country, tg_id, client_id, email, expiry_ms, plan=months, session=session)
|
||||
|
||||
await state.clear()
|
||||
await callback_query.message.edit_text(
|
||||
@@ -946,15 +935,7 @@ async def handle_create_key_duration(callback_query: CallbackQuery, state: FSMCo
|
||||
|
||||
elif "cluster_name" in data:
|
||||
cluster_name = data["cluster_name"]
|
||||
await create_key_on_cluster(
|
||||
cluster_name,
|
||||
tg_id,
|
||||
client_id,
|
||||
email,
|
||||
expiry_ms,
|
||||
plan=months,
|
||||
session=session
|
||||
)
|
||||
await create_key_on_cluster(cluster_name, tg_id, client_id, email, expiry_ms, plan=months, session=session)
|
||||
|
||||
await state.clear()
|
||||
await callback_query.message.edit_text(
|
||||
@@ -968,8 +949,7 @@ async def handle_create_key_duration(callback_query: CallbackQuery, state: FSMCo
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при создании ключа: {e}")
|
||||
await callback_query.message.edit_text(
|
||||
"❌ Не удалось создать ключ. Попробуйте позже.",
|
||||
reply_markup=build_editor_kb(data.get("tg_id", 0))
|
||||
"❌ Не удалось создать ключ. Попробуйте позже.", reply_markup=build_editor_kb(data.get("tg_id", 0))
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user