refactor: migrate trial subscription to database-driven tariffs
This commit is contained in:
@@ -103,7 +103,8 @@ async def start_tariff_creation(callback: CallbackQuery, state: FSMContext):
|
||||
"<b>Специальные группы:</b>\n"
|
||||
"• <code>discounts</code> — тарифы со скидкой\n"
|
||||
"• <code>discounts_max</code> — тарифы с максимальной скидкой\n"
|
||||
"• <code>gifts</code> — тарифы для подарков",
|
||||
"• <code>gifts</code> — тарифы для подарков\n"
|
||||
"• <code>trial</code> — тариф для пробного периода",
|
||||
reply_markup=build_cancel_kb(),
|
||||
)
|
||||
|
||||
@@ -276,6 +277,7 @@ async def show_tariff_groups(callback: CallbackQuery, session: AsyncSession):
|
||||
"discounts": "🔻 Скидки",
|
||||
"discounts_max": "🔻 Макс. скидки",
|
||||
"gifts": "🎁 Подарки",
|
||||
"trial": "🚀 Пробный период",
|
||||
}
|
||||
|
||||
text = "<b>📋 Выберите тарифную группу:</b>\n\n"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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"]
|
||||
|
||||
+10
-11
@@ -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] = []
|
||||
|
||||
Reference in New Issue
Block a user