diff --git a/handlers/admin/tariffs/tariffs_handler.py b/handlers/admin/tariffs/tariffs_handler.py index f4a939da..f2160296 100644 --- a/handlers/admin/tariffs/tariffs_handler.py +++ b/handlers/admin/tariffs/tariffs_handler.py @@ -103,7 +103,8 @@ async def start_tariff_creation(callback: CallbackQuery, state: FSMContext): "Специальные группы:\n" "• discounts — тарифы со скидкой\n" "• discounts_max — тарифы с максимальной скидкой\n" - "• gifts — тарифы для подарков", + "• gifts — тарифы для подарков\n" + "• trial — тариф для пробного периода", reply_markup=build_cancel_kb(), ) @@ -276,6 +277,7 @@ async def show_tariff_groups(callback: CallbackQuery, session: AsyncSession): "discounts": "🔻 Скидки", "discounts_max": "🔻 Макс. скидки", "gifts": "🎁 Подарки", + "trial": "🚀 Пробный период", } text = "📋 Выберите тарифную группу:\n\n" diff --git a/handlers/keys/key_freeze.py b/handlers/keys/key_freeze.py index 8b03fe32..a0bad251 100644 --- a/handlers/keys/key_freeze.py +++ b/handlers/keys/key_freeze.py @@ -7,7 +7,6 @@ from aiogram.types import CallbackQuery, InlineKeyboardButton from aiogram.utils.keyboard import InlineKeyboardBuilder from sqlalchemy import text -from config import TRIAL_CONFIG from database import ( get_key_details, get_servers, @@ -89,9 +88,9 @@ async def process_callback_unfreeze_subscription_confirm(callback_query: Callbac tariff = await get_tariff_by_id(session, record["tariff_id"]) if record.get("tariff_id") else None if not tariff: - logger.info("[Unfreeze] Тариф не найден — возможно ключ триальный. Применяем дефолтные значения.") - total_gb = TRIAL_CONFIG["traffic_limit_gb"] - hwid_limit = TRIAL_CONFIG["hwid_limit"] + logger.info("[Unfreeze] Тариф не найден — применяем дефолтные значения.") + total_gb = 0 + hwid_limit = 0 else: total_gb = int(tariff.get("traffic_limit") or 0) hwid_limit = int(tariff.get("device_limit") or 0) diff --git a/handlers/keys/key_mode/key_cluster_mode.py b/handlers/keys/key_mode/key_cluster_mode.py index c70844e3..8dca9aa3 100644 --- a/handlers/keys/key_mode/key_cluster_mode.py +++ b/handlers/keys/key_mode/key_cluster_mode.py @@ -15,7 +15,7 @@ from aiogram.types import ( from aiogram.utils.keyboard import InlineKeyboardBuilder from bot import bot -from config import CONNECT_PHONE_BUTTON, SUPPORT_CHAT_URL, TRIAL_CONFIG +from config import CONNECT_PHONE_BUTTON, SUPPORT_CHAT_URL from database import ( get_key_details, get_tariff_by_id, @@ -23,6 +23,7 @@ from database import ( update_balance, update_trial, ) + from handlers.buttons import ( CONNECT_DEVICE, CONNECT_PHONE, @@ -84,10 +85,7 @@ async def key_cluster_mode( device_limit = 0 traffic_limit_gb = 0 - if is_trial: - device_limit = TRIAL_CONFIG.get("hwid_limit", 0) - traffic_limit_gb = TRIAL_CONFIG.get("traffic_limit_gb", 100) - elif plan: + if plan: tariff = await get_tariff_by_id(session, plan) if tariff: if tariff.get("device_limit") is not None: @@ -182,30 +180,16 @@ async def key_cluster_mode( if plan: tariff_info = await get_tariff_by_id(session, plan) - if is_trial: - trial_days = TRIAL_CONFIG.get("duration_days", 1) - if trial_days >= 30: - months = trial_days // 30 - tariff_duration = format_months(months) - else: - tariff_duration = format_days(trial_days) - key_message_text = key_message_success( - final_link, - tariff_name=tariff_duration, - traffic_limit=TRIAL_CONFIG.get("traffic_limit_gb", 100), - device_limit=TRIAL_CONFIG.get("hwid_limit", 0), - ) - else: - tariff_duration = tariff_info["name"] - subgroup_title = tariff_info.get("subgroup_title", "") if tariff_info else "" + tariff_duration = tariff_info["name"] + subgroup_title = tariff_info.get("subgroup_title", "") if tariff_info else "" - key_message_text = key_message_success( - final_link, - tariff_name=tariff_duration, - traffic_limit=tariff_info.get("traffic_limit", 0) if tariff_info else 0, - device_limit=tariff_info.get("device_limit", 0) if tariff_info else 0, - subgroup_title=subgroup_title, - ) + key_message_text = key_message_success( + final_link, + tariff_name=tariff_duration, + traffic_limit=tariff_info.get("traffic_limit", 0) if tariff_info else 0, + device_limit=tariff_info.get("device_limit", 0) if tariff_info else 0, + subgroup_title=subgroup_title, + ) default_media_path = "img/pic.jpg" if safe_to_edit: diff --git a/handlers/keys/key_mode/key_country_mode.py b/handlers/keys/key_mode/key_country_mode.py index 9c994211..2f469026 100644 --- a/handlers/keys/key_mode/key_country_mode.py +++ b/handlers/keys/key_mode/key_country_mode.py @@ -24,7 +24,6 @@ from config import ( REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, SUPPORT_CHAT_URL, - TRIAL_CONFIG, ) from database import ( add_user, @@ -34,7 +33,9 @@ from database import ( get_trial, update_balance, update_trial, + get_tariff_by_id, ) + from database.models import Key, Server, Tariff from handlers.buttons import BACK, CONNECT_DEVICE, CONNECT_PHONE, MAIN_MENU, MY_SUB, PC_BUTTON, SUPPORT, TV_BUTTON from handlers.keys.key_utils import create_client_on_server @@ -335,10 +336,7 @@ async def finalize_key_creation( data = await state.get_data() if state else {} is_trial = data.get("is_trial", False) - if is_trial: - traffic_limit_bytes = int(TRIAL_CONFIG.get("traffic_limit_gb", 100)) * 1024**3 - device_limit = TRIAL_CONFIG.get("hwid_limit", 0) - elif data.get("tariff_id") or tariff_id: + if data.get("tariff_id") or tariff_id: tariff_id = data.get("tariff_id") or tariff_id result = await session.execute(select(Tariff).where(Tariff.id == tariff_id)) tariff = result.scalar_one_or_none() @@ -511,30 +509,16 @@ async def finalize_key_creation( result = await session.execute(select(Tariff).where(Tariff.id == tariff_id)) tariff_info = result.scalar_one_or_none() - if is_trial: - trial_days = TRIAL_CONFIG.get("duration_days", 1) - if trial_days >= 30: - months = trial_days // 30 - tariff_duration = format_months(months) - else: - tariff_duration = format_days(trial_days) - key_message_text = key_message_success( - link_to_show, - tariff_name=tariff_duration, - traffic_limit=TRIAL_CONFIG.get("traffic_limit_gb", 100), - device_limit=TRIAL_CONFIG.get("hwid_limit", 0), - ) - else: - tariff_duration = tariff_info["name"] if tariff_info else None - subgroup_title = tariff_info.get("subgroup_title", "") if tariff_info else "" + tariff_duration = tariff_info["name"] + subgroup_title = tariff_info.get("subgroup_title", "") if tariff_info else "" - key_message_text = key_message_success( - link_to_show, - tariff_name=tariff_duration, - traffic_limit=tariff_info.get("traffic_limit", 0) if tariff_info else 0, - device_limit=tariff_info.get("device_limit", 0) if tariff_info else 0, - subgroup_title=subgroup_title, - ) + key_message_text = key_message_success( + link_to_show, + tariff_name=tariff_duration, + traffic_limit=tariff_info.get("traffic_limit", 0) if tariff_info else 0, + device_limit=tariff_info.get("device_limit", 0) if tariff_info else 0, + subgroup_title=subgroup_title, + ) await edit_or_send_message( target_message=callback_query.message, diff --git a/handlers/keys/key_mode/key_create.py b/handlers/keys/key_mode/key_create.py index 7510c270..e8cc269d 100644 --- a/handlers/keys/key_mode/key_create.py +++ b/handlers/keys/key_mode/key_create.py @@ -14,7 +14,6 @@ from sqlalchemy.ext.asyncio import AsyncSession from config import ( NOTIFY_EXTRA_DAYS, - TRIAL_CONFIG, TRIAL_TIME_DISABLE, USE_COUNTRY_SELECTION, USE_NEW_PAYMENT_FLOW, @@ -29,7 +28,7 @@ from database import ( get_trial, ) from database.models import Admin -from database.tariffs import create_subgroup_hash, find_subgroup_by_hash +from database.tariffs import create_subgroup_hash, find_subgroup_by_hash, get_tariffs from handlers.admin.panel.keyboard import AdminPanelCallback from handlers.buttons import MAIN_MENU, PAYMENT from handlers.payments.robokassa_pay import handle_custom_amount_input @@ -90,7 +89,21 @@ async def handle_key_creation( if not TRIAL_TIME_DISABLE: trial_status = await get_trial(session, tg_id) if trial_status in [0, -1]: - base_days = TRIAL_CONFIG["duration_days"] + trial_tariffs = await get_tariffs(session, group_code="trial") + if not trial_tariffs: + await edit_or_send_message( + target_message=( + message_or_query.message if isinstance(message_or_query, CallbackQuery) else message_or_query + ), + text="❌ Пробная подписка временно недоступна.", + reply_markup=InlineKeyboardBuilder() + .row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile")) + .as_markup(), + ) + return + + trial_tariff = trial_tariffs[0] + base_days = trial_tariff["duration_days"] extra_days = NOTIFY_EXTRA_DAYS if trial_status == -1 else 0 total_days = base_days + extra_days expiry_time = current_time + timedelta(days=total_days) @@ -105,8 +118,8 @@ async def handle_key_creation( reply_markup=None, ) - await state.update_data(is_trial=True) - await create_key(tg_id, expiry_time, state, session, message_or_query) + await state.update_data(is_trial=True, plan=trial_tariff["id"]) + await create_key(tg_id, expiry_time, state, session, message_or_query, plan=trial_tariff["id"]) return try: diff --git a/handlers/keys/key_renew.py b/handlers/keys/key_renew.py index 760bf1e6..62782f9d 100644 --- a/handlers/keys/key_renew.py +++ b/handlers/keys/key_renew.py @@ -92,7 +92,7 @@ async def process_callback_renew_key(callback_query: CallbackQuery, state: FSMCo 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"]: + if current_tariff["group_code"] not in ["discounts", "discounts_max", "gifts", "trial"]: group_code = current_tariff["group_code"] tariffs = await get_tariffs(session, group_code=group_code) diff --git a/handlers/keys/key_utils.py b/handlers/keys/key_utils.py index 7ebea152..5391b7f5 100644 --- a/handlers/keys/key_utils.py +++ b/handlers/keys/key_utils.py @@ -6,8 +6,9 @@ from typing import Any from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession -from config import PUBLIC_LINK, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, SUPERNODE, TRIAL_CONFIG +from config import PUBLIC_LINK, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, SUPERNODE from database import delete_notification, get_servers, get_tariff_by_id, store_key + from database.models import Key, Server, Tariff from handlers.utils import check_server_key_limit, get_least_loaded_cluster from logger import logger @@ -220,11 +221,7 @@ async def create_client_on_server( total_gb_value = 0 device_limit_value = 0 - if is_trial: - total_gb_value = TRIAL_CONFIG.get("traffic_limit_gb", 0) - device_limit_value = TRIAL_CONFIG.get("hwid_limit") - logger.info(f"[Trial] Используются параметры триала: {total_gb_value} GB, {device_limit_value} устройств") - elif plan is not None: + if plan is not None: tariff = await get_tariff_by_id(session, plan) logger.info(f"[Tariff Debug] Получен тариф: {tariff}") if not tariff: diff --git a/handlers/notifications/general_notifications.py b/handlers/notifications/general_notifications.py index 1b3a387f..b3983575 100644 --- a/handlers/notifications/general_notifications.py +++ b/handlers/notifications/general_notifications.py @@ -476,7 +476,7 @@ async def process_auto_renew_or_notify( 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"]: + if current_tariff["group_code"] in ["discounts", "discounts_max", "gifts", "trial"]: cluster_tariffs = [t for t in tariffs if t["is_active"] and balance >= t["price_rub"]] if cluster_tariffs: cluster_tariffs_31 = [t for t in cluster_tariffs if t["duration_days"] <= 31] diff --git a/handlers/notifications/special_notifications.py b/handlers/notifications/special_notifications.py index 7b21db83..5aad9898 100644 --- a/handlers/notifications/special_notifications.py +++ b/handlers/notifications/special_notifications.py @@ -13,7 +13,6 @@ from config import ( NOTIFY_INACTIVE, NOTIFY_INACTIVE_TRAFFIC, SUPPORT_CHAT_URL, - TRIAL_CONFIG, ) from database import ( add_notification, @@ -22,6 +21,7 @@ from database import ( update_key_notified, ) from database.models import Key +from database.tariffs import get_tariffs from handlers.buttons import CONNECT_DEVICE, CONNECT_PHONE, MAIN_MENU, PC_BUTTON, TV_BUTTON from handlers.keys.key_utils import get_user_traffic from handlers.notifications.notify_utils import send_messages_with_limit @@ -44,7 +44,12 @@ async def notify_inactive_trial_users(bot: Bot, session: AsyncSession): logger.info(f"Найдено {len(users)} неактивных пользователей для уведомления.") messages = [] - trial_days = TRIAL_CONFIG["duration_days"] + trial_tariffs = await get_tariffs(session, group_code="trial") + if not trial_tariffs: + logger.error("[Notifications] Триальный тариф не найден") + return + + trial_days = trial_tariffs[0]["duration_days"] for user in users: tg_id = user["tg_id"] diff --git a/handlers/refferal.py b/handlers/refferal.py index 29b26ad4..ec7d49cd 100644 --- a/handlers/refferal.py +++ b/handlers/refferal.py @@ -20,15 +20,7 @@ from sqlalchemy import desc, func, select from sqlalchemy.ext.asyncio import AsyncSession from bot import bot -from config import ( - ADMIN_ID, - INLINE_MODE, - REFERRAL_BONUS_PERCENTAGES, - REFERRAL_QR, - TOP_REFERRAL_BUTTON, - TRIAL_CONFIG, - USERNAME_BOT, -) +from config import ADMIN_ID, INLINE_MODE, REFERRAL_BONUS_PERCENTAGES, TOP_REFERRAL_BUTTON, USERNAME_BOT, REFERRAL_QR from database import ( add_referral, add_user, @@ -37,6 +29,7 @@ from database import ( get_referral_stats, ) from database.models import Referral +from database.tariffs import get_tariffs from handlers.buttons import BACK, INVITE, MAIN_MENU, QR, TOP_FIVE from handlers.texts import ( INVITE_MESSAGE_TEMPLATE, @@ -118,9 +111,15 @@ async def invite_handler(callback_query_or_message: Message | CallbackQuery, ses @router.inline_query(F.query.in_(["referral", "ref", "invite"])) -async def inline_referral_handler(inline_query: InlineQuery): +async def inline_referral_handler(inline_query: InlineQuery, session: AsyncSession): referral_link = f"https://t.me/{USERNAME_BOT}?start=referral_{inline_query.from_user.id}" - trial_days = TRIAL_CONFIG["duration_days"] + + trial_tariffs = await get_tariffs(session, group_code="trial") + if not trial_tariffs: + await inline_query.answer(results=[], cache_time=0) + return + + trial_days = trial_tariffs[0]["duration_days"] trial_time_formatted = format_days(trial_days) results: list[InlineQueryResultArticle] = []