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)