diff --git a/handlers/admin/users/keyboard.py b/handlers/admin/users/keyboard.py
index a1846419..4e3b8234 100644
--- a/handlers/admin/users/keyboard.py
+++ b/handlers/admin/users/keyboard.py
@@ -185,9 +185,9 @@ async def build_users_key_expiry_kb(
) -> InlineKeyboardMarkup:
builder = InlineKeyboardBuilder()
- result = await session.execute(select(Key.server_id).where(Key.email == email))
+ result = await session.execute(select(Key.server_id, Key.tariff_id).where(Key.email == email))
row = result.first()
- if not row or not row[0]:
+ if not row or not row[0] or not row[1]:
builder.row(
InlineKeyboardButton(
text="⚠️ Сервер не найден",
@@ -198,18 +198,17 @@ async def build_users_key_expiry_kb(
)
return builder.as_markup()
- server_id = row[0]
+ server_id, tariff_id = row
+
+ result = await session.execute(select(Tariff.group_code).where(Tariff.id == tariff_id))
+ row = result.first()
+ if not row or not row[0]:
+ return builder.as_markup()
+ group_code = row[0]
result = await session.execute(
select(Tariff)
- .join(Server, Tariff.group_code == Server.tariff_group)
- .where(
- or_(
- Server.server_name == server_id,
- Server.cluster_name == server_id,
- )
- )
-
+ .where(Tariff.group_code == group_code, Tariff.is_active.is_(True))
)
tariffs = result.scalars().all()
diff --git a/handlers/admin/users/users_handler.py b/handlers/admin/users/users_handler.py
index fed21338..dab9de22 100644
--- a/handlers/admin/users/users_handler.py
+++ b/handlers/admin/users/users_handler.py
@@ -526,13 +526,12 @@ async def handle_key_edit(
tariff_name = "—"
if key_details.get("tariff_id"):
-
result = await session.execute(
- select(Tariff.name).where(Tariff.id == key_details["tariff_id"])
+ select(Tariff.name, Tariff.group_code).where(Tariff.id == key_details["tariff_id"])
)
row = result.first()
if row:
- tariff_name = row[0]
+ tariff_name = f"{row[0]} ({row[1]})"
text = (
f"🔑 Информация о ключе"
@@ -730,7 +729,7 @@ async def handle_expiry_add(
):
tg_id = callback_data.tg_id
email = callback_data.data
- month = callback_data.month
+ days = callback_data.month
key_details = await get_key_details(session, email)
@@ -741,9 +740,9 @@ async def handle_expiry_add(
)
return
- if month:
+ if days:
await change_expiry_time(
- key_details["expiry_time"] + month * 30 * 24 * 3600 * 1000, email, session
+ key_details["expiry_time"] + days * 24 * 3600 * 1000, email, session
)
await handle_key_edit(callback_query, callback_data, session, True)
return
diff --git a/handlers/coupons.py b/handlers/coupons.py
index 45c6ecad..b072d97d 100644
--- a/handlers/coupons.py
+++ b/handlers/coupons.py
@@ -23,6 +23,7 @@ from database import (
update_coupon_usage_count,
update_key_expiry,
add_payment,
+ get_tariff_by_id,
)
from handlers.buttons import MAIN_MENU
from handlers.keys.key_utils import renew_key_in_cluster
@@ -230,12 +231,19 @@ async def handle_key_extension(
current_expiry = key.expiry_time
new_expiry = max(now_ms, current_expiry) + (coupon.days * 86400 * 1000)
+ tariff = None
+ if key.tariff_id:
+ tariff = await get_tariff_by_id(session, key.tariff_id)
+ total_gb = int(tariff["traffic_limit"]) if tariff and tariff.get("traffic_limit") else 0
+ device_limit = int(tariff["device_limit"]) if tariff and tariff.get("device_limit") else None
+
await renew_key_in_cluster(
cluster_id=key.server_id,
email=key.email,
client_id=client_id,
new_expiry_time=new_expiry,
- total_gb=0,
+ total_gb=total_gb,
+ hwid_device_limit=device_limit,
session=session
)
await update_key_expiry(session, client_id, new_expiry)
diff --git a/handlers/keys/key_renew.py b/handlers/keys/key_renew.py
index e242a3a9..c7a92059 100644
--- a/handlers/keys/key_renew.py
+++ b/handlers/keys/key_renew.py
@@ -18,6 +18,8 @@ from database import (
get_tariffs,
update_balance,
update_key_expiry,
+ check_tariff_exists,
+ get_tariffs_for_cluster,
)
from database.models import Server, Key
from handlers.buttons import BACK, MAIN_MENU, PAYMENT
@@ -54,8 +56,9 @@ async def process_callback_renew_key(
client_id = record["client_id"]
expiry_time = record["expiry_time"]
server_id = record["server_id"]
+ tariff_id = record.get("tariff_id")
- logger.info(f"[RENEW] Получение тарифной группы для server_id={server_id}")
+ logger.info(f"[RENEW] Получение тарифов для server_id={server_id}")
try:
server_id_int = int(server_id)
@@ -75,26 +78,35 @@ async def process_callback_renew_key(
)
row = row.first()
if not row or not row[0]:
- logger.warning(
- f"[RENEW] Тарифная группа не найдена для server_id={server_id}"
- )
- await callback_query.message.answer(
- "❌ Не удалось определить тарифную группу."
- )
+ logger.warning(f"[RENEW] Тарифная группа не найдена для server_id={server_id}")
+ await callback_query.message.answer("❌ Не удалось определить тарифную группу.")
return
- tariff_group = row[0]
- tariffs = await get_tariffs(session, group_code=tariff_group)
+ cluster_group = row[0]
+ selected_tariffs = []
+ target_group = cluster_group
+ if tariff_id:
+ if await check_tariff_exists(session, tariff_id):
+ current_tariff = await get_tariff_by_id(session, tariff_id)
+
+ if current_tariff["group_code"] not in ["discounts", "discounts_max", "gifts"]:
+ target_group = current_tariff["group_code"]
+
+ tariffs = await get_tariffs(session, group_code=target_group)
+
if not tariffs:
- logger.warning(f"[RENEW] Нет активных тарифов для группы '{tariff_group}'")
- await callback_query.message.answer(
- "❌ Нет доступных тарифов для этой группы."
- )
+ await callback_query.message.answer("❌ Нет доступных тарифов для продления.")
+ return
+
+ selected_tariffs = [t for t in tariffs if t["is_active"]]
+
+ if not selected_tariffs:
+ await callback_query.message.answer("❌ Нет доступных тарифов для продления.")
return
builder = InlineKeyboardBuilder()
- for t in tariffs:
+ for t in selected_tariffs:
button_text = f"📅 {t['name']} — {t['price_rub']}₽"
builder.row(
InlineKeyboardButton(
diff --git a/handlers/keys/key_view.py b/handlers/keys/key_view.py
index 425c1ec3..cbebdd15 100644
--- a/handlers/keys/key_view.py
+++ b/handlers/keys/key_view.py
@@ -22,7 +22,7 @@ from config import (
TOGGLE_CLIENT,
USE_COUNTRY_SELECTION,
)
-from database import get_key_details, get_keys, get_servers
+from database import get_key_details, get_keys, get_servers, get_tariff_by_id
from database.models import Key
from handlers.buttons import (
ADD_SUB,
@@ -256,7 +256,7 @@ async def render_key_info(
days = total_seconds // 86400
hours = (total_seconds % 86400) // 3600
minutes = (total_seconds % 3600) // 60
- days_left_message = f"Осталось: {format_days(days)}, {format_hours(hours)}, {format_minutes(minutes)}"
+ days_left_message = f"⏳ Осталось: {format_days(days)}, {format_hours(hours)}, {format_minutes(minutes)}"
formatted_expiry_date = f"{expiry_date.strftime('%d')} {get_russian_month(expiry_date)} {expiry_date.strftime('%Y')} года"
@@ -279,6 +279,16 @@ async def render_key_info(
devices = await api.get_user_hwid_devices(client_id)
hwid_count = len(devices or [])
+ tariff_name = ""
+ traffic_limit = 0
+ device_limit = 0
+ if record.get("tariff_id"):
+ tariff = await get_tariff_by_id(session, record["tariff_id"])
+ if tariff:
+ tariff_name = tariff["name"]
+ traffic_limit = tariff.get("traffic_limit", 0)
+ device_limit = tariff.get("device_limit", 0)
+
response_message = key_message(
final_link,
formatted_expiry_date,
@@ -286,6 +296,9 @@ async def render_key_info(
server_name,
server_name if USE_COUNTRY_SELECTION else None,
hwid_count=hwid_count,
+ tariff_name=tariff_name,
+ traffic_limit=traffic_limit,
+ device_limit=device_limit
)
if ENABLE_UPDATE_SUBSCRIPTION_BUTTON:
diff --git a/handlers/notifications/general_notifications.py b/handlers/notifications/general_notifications.py
index a2106e5a..54007af8 100644
--- a/handlers/notifications/general_notifications.py
+++ b/handlers/notifications/general_notifications.py
@@ -545,20 +545,32 @@ async def process_auto_renew_or_notify(
if not tariff_id:
cluster_tariffs = [t for t in tariffs if t["is_active"] and balance >= t["price_rub"]]
if cluster_tariffs:
- selected_tariff = max(cluster_tariffs, key=lambda x: min(x["duration_days"], 31))
+ cluster_tariffs_31 = [t for t in cluster_tariffs if t["duration_days"] <= 31]
+ if cluster_tariffs_31:
+ selected_tariff = max(cluster_tariffs_31, key=lambda x: x["duration_days"])
+ else:
+ selected_tariff = None
else:
if await check_tariff_exists(conn, tariff_id):
current_tariff = await get_tariff_by_id(conn, tariff_id)
if current_tariff["group_code"] in ["discounts", "discounts_max", "gifts"]:
cluster_tariffs = [t for t in tariffs if t["is_active"] and balance >= t["price_rub"]]
if cluster_tariffs:
- selected_tariff = max(cluster_tariffs, key=lambda x: min(x["duration_days"], 31))
+ cluster_tariffs_31 = [t for t in cluster_tariffs if t["duration_days"] <= 31]
+ if cluster_tariffs_31:
+ selected_tariff = max(cluster_tariffs_31, key=lambda x: x["duration_days"])
+ else:
+ selected_tariff = None
elif balance >= current_tariff["price_rub"]:
selected_tariff = current_tariff
else:
cluster_tariffs = [t for t in tariffs if t["is_active"] and balance >= t["price_rub"]]
if cluster_tariffs:
- selected_tariff = max(cluster_tariffs, key=lambda x: min(x["duration_days"], 31))
+ cluster_tariffs_31 = [t for t in cluster_tariffs if t["duration_days"] <= 31]
+ if cluster_tariffs_31:
+ selected_tariff = max(cluster_tariffs_31, key=lambda x: x["duration_days"])
+ else:
+ selected_tariff = None
if not selected_tariff:
keyboard = build_notification_kb(email)
diff --git a/handlers/start.py b/handlers/start.py
index 63b63ba9..cc03bc66 100644
--- a/handlers/start.py
+++ b/handlers/start.py
@@ -19,7 +19,7 @@ from config import (
SHOW_START_MENU_ONCE,
SUPPORT_CHAT_URL,
)
-from database import add_user, check_user_exists, get_trial
+from database import add_user, check_user_exists, get_trial, get_key_count
from database.models import TrackingSource, User
from handlers.buttons import (
ABOUT_VPN,
@@ -229,12 +229,15 @@ async def process_start_logic(
await add_user(session=session, **user_data)
trial_status = await get_trial(session, user_data["tg_id"])
+ key_count = await get_key_count(session, user_data["tg_id"])
if SHOW_START_MENU_ONCE:
- if trial_status > 0:
+ if key_count > 0:
await process_callback_view_profile(message, state, admin, session)
- else:
+ elif trial_status == 0:
await show_start_menu(message, admin, session)
+ else:
+ await process_callback_view_profile(message, state, admin, session)
else:
await show_start_menu(message, admin, session)