Optimize user activity updates and fix traffic top-up
This commit is contained in:
+12
-15
@@ -18,7 +18,6 @@ from database import (
|
||||
add_payment,
|
||||
add_user,
|
||||
check_coupon_usage,
|
||||
check_user_exists,
|
||||
create_coupon_usage,
|
||||
get_coupon_by_code,
|
||||
get_keys,
|
||||
@@ -108,20 +107,18 @@ async def activate_coupon(
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
user_exists = await check_user_exists(session, user_id)
|
||||
if not user_exists:
|
||||
if isinstance(user, dict):
|
||||
await add_user(session=session, **user)
|
||||
else:
|
||||
await add_user(
|
||||
session=session,
|
||||
tg_id=user.id,
|
||||
username=getattr(user, "username", None),
|
||||
first_name=getattr(user, "first_name", None),
|
||||
last_name=getattr(user, "last_name", None),
|
||||
language_code=getattr(user, "language_code", None),
|
||||
is_bot=getattr(user, "is_bot", False),
|
||||
)
|
||||
if isinstance(user, dict):
|
||||
await add_user(session=session, **user)
|
||||
else:
|
||||
await add_user(
|
||||
session=session,
|
||||
tg_id=user.id,
|
||||
username=getattr(user, "username", None),
|
||||
first_name=getattr(user, "first_name", None),
|
||||
last_name=getattr(user, "last_name", None),
|
||||
language_code=getattr(user, "language_code", None),
|
||||
is_bot=getattr(user, "is_bot", False),
|
||||
)
|
||||
|
||||
if coupon.amount > 0:
|
||||
try:
|
||||
|
||||
+11
-13
@@ -20,7 +20,6 @@ from config import (
|
||||
from core.bootstrap import MODES_CONFIG, NOTIFICATIONS_CONFIG
|
||||
from database import (
|
||||
add_user,
|
||||
check_user_exists,
|
||||
get_tariffs_for_cluster,
|
||||
get_trial,
|
||||
)
|
||||
@@ -393,18 +392,17 @@ async def create_key(
|
||||
selected_traffic_gb: int | None = None,
|
||||
selected_price_rub: int | None = None,
|
||||
):
|
||||
if not await check_user_exists(session, tg_id):
|
||||
from_user = message_or_query.from_user if isinstance(message_or_query, CallbackQuery | Message) else None
|
||||
if from_user:
|
||||
await add_user(
|
||||
tg_id=from_user.id,
|
||||
username=from_user.username,
|
||||
first_name=from_user.first_name,
|
||||
last_name=from_user.last_name,
|
||||
language_code=from_user.language_code,
|
||||
is_bot=from_user.is_bot,
|
||||
session=session,
|
||||
)
|
||||
from_user = message_or_query.from_user if isinstance(message_or_query, CallbackQuery | Message) else None
|
||||
if from_user:
|
||||
await add_user(
|
||||
tg_id=from_user.id,
|
||||
username=from_user.username,
|
||||
first_name=from_user.first_name,
|
||||
last_name=from_user.last_name,
|
||||
language_code=from_user.language_code,
|
||||
is_bot=from_user.is_bot,
|
||||
session=session,
|
||||
)
|
||||
|
||||
use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION))
|
||||
|
||||
|
||||
+14
-16
@@ -25,7 +25,6 @@ from core.bootstrap import BUTTONS_CONFIG, MODES_CONFIG
|
||||
from database import (
|
||||
add_referral,
|
||||
add_user,
|
||||
check_user_exists,
|
||||
get_referral_by_referred_id,
|
||||
get_referral_stats,
|
||||
)
|
||||
@@ -271,23 +270,22 @@ async def handle_referral_link(
|
||||
await message.answer("❌ Вы уже использовали реферальную ссылку.")
|
||||
return
|
||||
|
||||
user_exists = await check_user_exists(session, user_id)
|
||||
if user_exists:
|
||||
if isinstance(user, dict):
|
||||
inserted = await add_user(session=session, **user)
|
||||
else:
|
||||
inserted = await add_user(
|
||||
session=session,
|
||||
tg_id=user.id,
|
||||
username=getattr(user, "username", None),
|
||||
first_name=getattr(user, "first_name", None),
|
||||
last_name=getattr(user, "last_name", None),
|
||||
language_code=getattr(user, "language_code", None),
|
||||
is_bot=getattr(user, "is_bot", False),
|
||||
)
|
||||
|
||||
if not inserted:
|
||||
await message.answer("❌ Вы уже зарегистрированы и не можете стать рефералом.")
|
||||
return
|
||||
if not user_exists:
|
||||
if isinstance(user, dict):
|
||||
await add_user(session=session, **user)
|
||||
else:
|
||||
await add_user(
|
||||
session=session,
|
||||
tg_id=user.id,
|
||||
username=getattr(user, "username", None),
|
||||
first_name=getattr(user, "first_name", None),
|
||||
last_name=getattr(user, "last_name", None),
|
||||
language_code=getattr(user, "language_code", None),
|
||||
is_bot=getattr(user, "is_bot", False),
|
||||
)
|
||||
|
||||
await add_referral(session, user_id, referrer_tg_id)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from aiogram import F, Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from config import USE_NEW_PAYMENT_FLOW
|
||||
@@ -17,6 +18,7 @@ from database import (
|
||||
save_key_config_with_mode,
|
||||
update_balance,
|
||||
)
|
||||
from database.models import User
|
||||
from handlers.buttons import BACK, CONFIRM_ADDON_BUTTON_TEXT, PAYMENT
|
||||
from handlers.keys.key_view import render_key_info
|
||||
from handlers.payments.currency_rates import format_for_user
|
||||
@@ -613,252 +615,274 @@ async def handle_addons_confirm(callback: CallbackQuery, state: FSMContext, sess
|
||||
tg_id = callback.from_user.id
|
||||
data = await state.get_data()
|
||||
|
||||
email = data.get("addon_key_email")
|
||||
tariff_id = data.get("addon_tariff_id")
|
||||
selected_devices = data.get("addon_selected_device_limit")
|
||||
selected_traffic_gb = data.get("addon_selected_traffic_gb")
|
||||
current_devices = data.get("addon_current_device_limit")
|
||||
current_traffic_gb = data.get("addon_current_traffic_gb")
|
||||
|
||||
logger.info(
|
||||
"[ADDONS] PACK_MODE handle_addons_confirm: "
|
||||
f"tg_id={tg_id} email={email} tariff_id={tariff_id} "
|
||||
f"selected_devices={selected_devices} selected_traffic_gb={selected_traffic_gb} "
|
||||
f"current_devices={current_devices} current_traffic_gb={current_traffic_gb}"
|
||||
)
|
||||
|
||||
if not email or not tariff_id:
|
||||
await callback.message.answer("❌ Данные для изменения подписки не найдены.")
|
||||
await state.clear()
|
||||
if data.get("addon_confirm_in_progress"):
|
||||
await callback.answer("⏳ Уже обрабатываю...", show_alert=False)
|
||||
return
|
||||
|
||||
record = await get_key_details(session, email)
|
||||
if not record:
|
||||
logger.warning(f"[ADDONS] PACK_MODE: подписка {email} не найдена в handle_addons_confirm")
|
||||
await callback.message.answer("❌ Подписка не найдена.")
|
||||
await state.clear()
|
||||
return
|
||||
await state.update_data(addon_confirm_in_progress=True)
|
||||
|
||||
tariff = await get_tariff_by_id(session, int(tariff_id))
|
||||
if not tariff:
|
||||
logger.error(f"[ADDONS] PACK_MODE: тариф {tariff_id} не найден в handle_addons_confirm")
|
||||
await callback.message.answer("❌ Тариф не найден.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
cfg = data.get("addon_tariff_config") or {}
|
||||
device_options = cfg.get("device_options") or []
|
||||
traffic_options = cfg.get("traffic_options_gb") or []
|
||||
|
||||
pack_devices, pack_traffic, pack_mode = get_pack_flags()
|
||||
|
||||
has_device_option = pack_devices and bool(device_options)
|
||||
has_traffic_option = pack_traffic and bool(traffic_options)
|
||||
|
||||
if has_device_option and current_devices is not None and int(current_devices) == 0:
|
||||
has_device_option = False
|
||||
selected_devices = None
|
||||
|
||||
if has_traffic_option and current_traffic_gb is not None and int(current_traffic_gb) == 0:
|
||||
has_traffic_option = False
|
||||
selected_traffic_gb = None
|
||||
|
||||
current_devices_for_price = int(current_devices) if current_devices is not None else None
|
||||
current_traffic_for_price = int(current_traffic_gb) if current_traffic_gb is not None else None
|
||||
|
||||
base_price_for_current = calculate_config_price(
|
||||
tariff=tariff,
|
||||
selected_device_limit=current_devices_for_price,
|
||||
selected_traffic_gb=current_traffic_for_price,
|
||||
)
|
||||
try:
|
||||
base_price_for_current_int = int(base_price_for_current) if base_price_for_current is not None else 0
|
||||
except (TypeError, ValueError):
|
||||
base_price_for_current_int = 0
|
||||
|
||||
recalc_enabled = bool(
|
||||
MODES_CONFIG.get(
|
||||
"KEY_ADDONS_RECALC_PRICE",
|
||||
TARIFFS_CONFIG.get("KEY_ADDONS_RECALC_PRICE", False),
|
||||
)
|
||||
)
|
||||
|
||||
diff_full = calc_pack_full_price_rub(
|
||||
tariff=tariff,
|
||||
has_device_option=has_device_option,
|
||||
has_traffic_option=has_traffic_option,
|
||||
selected_devices=int(selected_devices) if selected_devices is not None else None,
|
||||
selected_traffic_gb=int(selected_traffic_gb) if selected_traffic_gb is not None else None,
|
||||
)
|
||||
|
||||
if recalc_enabled:
|
||||
remaining_seconds, total_seconds = calc_remaining_ratio_seconds(record.get("expiry_time"), tariff)
|
||||
extra_price = int((diff_full * remaining_seconds + total_seconds - 1) // total_seconds)
|
||||
total_price_after_purchase = base_price_for_current_int + extra_price
|
||||
else:
|
||||
extra_price = int(diff_full)
|
||||
total_price_after_purchase = base_price_for_current_int + diff_full
|
||||
|
||||
logger.debug(
|
||||
"[ADDONS] PACK_MODE confirm prices: "
|
||||
f"base_price_for_current={base_price_for_current_int} diff_full={diff_full} "
|
||||
f"extra_price={extra_price} recalc_enabled={recalc_enabled} total_price_after_purchase={total_price_after_purchase} "
|
||||
f"has_device_option={has_device_option} has_traffic_option={has_traffic_option} "
|
||||
f"pack_mode={pack_mode!r}"
|
||||
)
|
||||
|
||||
if extra_price <= 0:
|
||||
logger.info(f"[ADDONS] PACK_MODE: extra_price <= 0, доплата не требуется, email={email}")
|
||||
await state.clear()
|
||||
await render_key_info(callback.message, session, email, "img/pic_view.jpg")
|
||||
await callback.answer(ADDONS_NO_EXTRA_PAYMENT_TEXT, show_alert=True)
|
||||
return
|
||||
|
||||
balance = await get_balance(session, tg_id)
|
||||
logger.debug(f"[ADDONS] PACK_MODE balance check: tg_id={tg_id} balance={balance} extra_price={extra_price}")
|
||||
|
||||
if balance < extra_price:
|
||||
required_amount = ceil(extra_price - balance)
|
||||
language_code = getattr(callback.from_user, "language_code", None)
|
||||
required_amount_text = await format_for_user(session, tg_id, float(required_amount), language_code)
|
||||
email = data.get("addon_key_email")
|
||||
tariff_id = data.get("addon_tariff_id")
|
||||
selected_devices = data.get("addon_selected_device_limit")
|
||||
selected_traffic_gb = data.get("addon_selected_traffic_gb")
|
||||
current_devices = data.get("addon_current_device_limit")
|
||||
current_traffic_gb = data.get("addon_current_traffic_gb")
|
||||
|
||||
logger.info(
|
||||
"[ADDONS] PACK_MODE: недостаточно средств "
|
||||
f"balance={balance} extra_price={extra_price} required_amount={required_amount} "
|
||||
f"tg_id={tg_id} USE_NEW_PAYMENT_FLOW={USE_NEW_PAYMENT_FLOW}"
|
||||
"[ADDONS] PACK_MODE handle_addons_confirm: "
|
||||
f"tg_id={tg_id} email={email} tariff_id={tariff_id} "
|
||||
f"selected_devices={selected_devices} selected_traffic_gb={selected_traffic_gb} "
|
||||
f"current_devices={current_devices} current_traffic_gb={current_traffic_gb}"
|
||||
)
|
||||
|
||||
if USE_NEW_PAYMENT_FLOW:
|
||||
handled = await try_fast_payment_flow(
|
||||
callback,
|
||||
session,
|
||||
state,
|
||||
tg_id=tg_id,
|
||||
temp_key="waiting_for_addons_payment",
|
||||
temp_payload={
|
||||
"email": email,
|
||||
"tariff_id": int(tariff_id),
|
||||
"selected_device_limit": selected_devices,
|
||||
"selected_traffic_gb": selected_traffic_gb,
|
||||
"current_device_limit": current_devices,
|
||||
"current_traffic_gb": current_traffic_gb,
|
||||
"required_amount": required_amount,
|
||||
},
|
||||
required_amount=required_amount,
|
||||
)
|
||||
logger.debug(f"[ADDONS] PACK_MODE try_fast_payment_flow handled={handled} tg_id={tg_id} email={email}")
|
||||
if handled:
|
||||
return
|
||||
if not email or not tariff_id:
|
||||
await callback.message.answer("❌ Данные для изменения подписки не найдены.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
|
||||
await edit_or_send_message(
|
||||
target_message=callback.message,
|
||||
text=INSUFFICIENT_FUNDS_RENEWAL_MSG.format(required_amount=required_amount_text),
|
||||
reply_markup=builder.as_markup(),
|
||||
record = await get_key_details(session, email)
|
||||
if not record:
|
||||
logger.warning(f"[ADDONS] PACK_MODE: подписка {email} не найдена в handle_addons_confirm")
|
||||
await callback.message.answer("❌ Подписка не найдена.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
tariff = await get_tariff_by_id(session, int(tariff_id))
|
||||
if not tariff:
|
||||
logger.error(f"[ADDONS] PACK_MODE: тариф {tariff_id} не найден в handle_addons_confirm")
|
||||
await callback.message.answer("❌ Тариф не найден.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
cfg = data.get("addon_tariff_config") or {}
|
||||
device_options = cfg.get("device_options") or []
|
||||
traffic_options = cfg.get("traffic_options_gb") or []
|
||||
|
||||
pack_devices, pack_traffic, pack_mode = get_pack_flags()
|
||||
|
||||
has_device_option = pack_devices and bool(device_options)
|
||||
has_traffic_option = pack_traffic and bool(traffic_options)
|
||||
|
||||
if has_device_option and current_devices is not None and int(current_devices) == 0:
|
||||
has_device_option = False
|
||||
selected_devices = None
|
||||
|
||||
if has_traffic_option and current_traffic_gb is not None and int(current_traffic_gb) == 0:
|
||||
has_traffic_option = False
|
||||
selected_traffic_gb = None
|
||||
|
||||
current_devices_for_price = int(current_devices) if current_devices is not None else None
|
||||
current_traffic_for_price = int(current_traffic_gb) if current_traffic_gb is not None else None
|
||||
|
||||
base_price_for_current = calculate_config_price(
|
||||
tariff=tariff,
|
||||
selected_device_limit=current_devices_for_price,
|
||||
selected_traffic_gb=current_traffic_for_price,
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
expiry_time = record["expiry_time"]
|
||||
client_id = record["client_id"]
|
||||
server_id = record["server_id"]
|
||||
|
||||
device_limit_effective_current, traffic_limit_bytes_effective_current = await get_effective_limits_for_key(
|
||||
session=session,
|
||||
tariff_id=int(tariff_id),
|
||||
selected_device_limit=int(current_devices) if current_devices is not None else None,
|
||||
selected_traffic_gb=int(current_traffic_gb) if current_traffic_gb is not None else None,
|
||||
)
|
||||
traffic_limit_gb_effective_current = (
|
||||
int(traffic_limit_bytes_effective_current / GB) if traffic_limit_bytes_effective_current else 0
|
||||
)
|
||||
|
||||
new_device_limit_effective = device_limit_effective_current
|
||||
new_traffic_limit_gb_effective = traffic_limit_gb_effective_current
|
||||
|
||||
if has_device_option and selected_devices is not None:
|
||||
pack_devices_val = int(selected_devices)
|
||||
if pack_devices_val <= 0 or (new_device_limit_effective is not None and new_device_limit_effective <= 0):
|
||||
new_device_limit_effective = 0
|
||||
else:
|
||||
if new_device_limit_effective is None:
|
||||
new_device_limit_effective = pack_devices_val
|
||||
else:
|
||||
new_device_limit_effective = new_device_limit_effective + pack_devices_val
|
||||
|
||||
if has_traffic_option and selected_traffic_gb is not None:
|
||||
pack_traffic_val = int(selected_traffic_gb)
|
||||
if pack_traffic_val <= 0 or new_traffic_limit_gb_effective <= 0:
|
||||
new_traffic_limit_gb_effective = 0
|
||||
else:
|
||||
new_traffic_limit_gb_effective = new_traffic_limit_gb_effective + pack_traffic_val
|
||||
|
||||
current_subgroup = None
|
||||
try:
|
||||
current_tariff_id = record.get("tariff_id")
|
||||
if current_tariff_id:
|
||||
current_tariff = await get_tariff_by_id(session, int(current_tariff_id))
|
||||
if current_tariff:
|
||||
current_subgroup = current_tariff.get("subgroup_title")
|
||||
except Exception as error:
|
||||
logger.warning(f"[ADDONS] PACK_MODE: не удалось определить текущую подгруппу: {error}")
|
||||
base_price_for_current_int = int(base_price_for_current) if base_price_for_current is not None else 0
|
||||
except (TypeError, ValueError):
|
||||
base_price_for_current_int = 0
|
||||
|
||||
target_subgroup = tariff.get("subgroup_title")
|
||||
old_subgroup = current_subgroup
|
||||
recalc_enabled = bool(
|
||||
MODES_CONFIG.get(
|
||||
"KEY_ADDONS_RECALC_PRICE",
|
||||
TARIFFS_CONFIG.get("KEY_ADDONS_RECALC_PRICE", False),
|
||||
)
|
||||
)
|
||||
|
||||
total_gb = new_traffic_limit_gb_effective
|
||||
hwid_device_limit_to_set = new_device_limit_effective
|
||||
diff_full = calc_pack_full_price_rub(
|
||||
tariff=tariff,
|
||||
has_device_option=has_device_option,
|
||||
has_traffic_option=has_traffic_option,
|
||||
selected_devices=int(selected_devices) if selected_devices is not None else None,
|
||||
selected_traffic_gb=int(selected_traffic_gb) if selected_traffic_gb is not None else None,
|
||||
)
|
||||
|
||||
if recalc_enabled:
|
||||
remaining_seconds, total_seconds = calc_remaining_ratio_seconds(record.get("expiry_time"), tariff)
|
||||
extra_price = int((diff_full * remaining_seconds + total_seconds - 1) // total_seconds)
|
||||
total_price_after_purchase = base_price_for_current_int + extra_price
|
||||
else:
|
||||
extra_price = int(diff_full)
|
||||
total_price_after_purchase = base_price_for_current_int + diff_full
|
||||
|
||||
logger.debug(
|
||||
"[ADDONS] PACK_MODE renew_key_in_cluster params: "
|
||||
f"server_id={server_id} email={email} client_id={client_id} total_gb={total_gb} "
|
||||
f"hwid_device_limit_to_set={hwid_device_limit_to_set} target_subgroup={target_subgroup} "
|
||||
f"old_subgroup={old_subgroup}"
|
||||
"[ADDONS] PACK_MODE confirm prices: "
|
||||
f"base_price_for_current={base_price_for_current_int} diff_full={diff_full} "
|
||||
f"extra_price={extra_price} recalc_enabled={recalc_enabled} total_price_after_purchase={total_price_after_purchase} "
|
||||
f"has_device_option={has_device_option} has_traffic_option={has_traffic_option} "
|
||||
f"pack_mode={pack_mode!r}"
|
||||
)
|
||||
|
||||
await renew_key_in_cluster(
|
||||
cluster_id=server_id,
|
||||
email=email,
|
||||
client_id=client_id,
|
||||
new_expiry_time=expiry_time,
|
||||
total_gb=total_gb,
|
||||
session=session,
|
||||
hwid_device_limit=hwid_device_limit_to_set,
|
||||
reset_traffic=False,
|
||||
target_subgroup=target_subgroup,
|
||||
old_subgroup=old_subgroup,
|
||||
plan=int(tariff_id),
|
||||
)
|
||||
if extra_price <= 0:
|
||||
logger.info(f"[ADDONS] PACK_MODE: extra_price <= 0, доплата не требуется, email={email}")
|
||||
await state.clear()
|
||||
await render_key_info(callback.message, session, email, "img/pic_view.jpg")
|
||||
await callback.answer(ADDONS_NO_EXTRA_PAYMENT_TEXT, show_alert=True)
|
||||
return
|
||||
|
||||
await update_balance(session, tg_id, -extra_price)
|
||||
balance = await get_balance(session, tg_id)
|
||||
logger.debug(f"[ADDONS] PACK_MODE balance check: tg_id={tg_id} balance={balance} extra_price={extra_price}")
|
||||
|
||||
await save_key_config_with_mode(
|
||||
session=session,
|
||||
email=email,
|
||||
selected_devices=new_device_limit_effective,
|
||||
selected_traffic_gb=new_traffic_limit_gb_effective,
|
||||
total_price=int(total_price_after_purchase),
|
||||
has_device_choice=has_device_option,
|
||||
has_traffic_choice=has_traffic_option,
|
||||
config_mode="pack",
|
||||
)
|
||||
if balance < extra_price:
|
||||
required_amount = ceil(extra_price - balance)
|
||||
language_code = getattr(callback.from_user, "language_code", None)
|
||||
required_amount_text = await format_for_user(session, tg_id, float(required_amount), language_code)
|
||||
|
||||
await session.commit()
|
||||
logger.info(
|
||||
"[ADDONS] PACK_MODE: недостаточно средств "
|
||||
f"balance={balance} extra_price={extra_price} required_amount={required_amount} "
|
||||
f"tg_id={tg_id} USE_NEW_PAYMENT_FLOW={USE_NEW_PAYMENT_FLOW}"
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"[ADDONS] PACK_MODE успешная покупка пакета: "
|
||||
f"tg_id={tg_id} email={email} extra_price={extra_price} "
|
||||
f"new_device_limit_effective={new_device_limit_effective} "
|
||||
f"new_traffic_limit_gb_effective={new_traffic_limit_gb_effective} "
|
||||
f"recalc_enabled={recalc_enabled} pack_mode={pack_mode!r}"
|
||||
)
|
||||
if USE_NEW_PAYMENT_FLOW:
|
||||
handled = await try_fast_payment_flow(
|
||||
callback,
|
||||
session,
|
||||
state,
|
||||
tg_id=tg_id,
|
||||
temp_key="waiting_for_addons_payment",
|
||||
temp_payload={
|
||||
"email": email,
|
||||
"tariff_id": int(tariff_id),
|
||||
"selected_device_limit": selected_devices,
|
||||
"selected_traffic_gb": selected_traffic_gb,
|
||||
"current_device_limit": current_devices,
|
||||
"current_traffic_gb": current_traffic_gb,
|
||||
"required_amount": required_amount,
|
||||
},
|
||||
required_amount=required_amount,
|
||||
)
|
||||
logger.debug(f"[ADDONS] PACK_MODE try_fast_payment_flow handled={handled} tg_id={tg_id} email={email}")
|
||||
if handled:
|
||||
return
|
||||
|
||||
await state.clear()
|
||||
await render_key_info(callback.message, session, email, "img/pic_view.jpg")
|
||||
await callback.answer(ADDONS_PACK_SUCCESS_TEXT, show_alert=True)
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=PAYMENT, callback_data="pay"))
|
||||
await edit_or_send_message(
|
||||
target_message=callback.message,
|
||||
text=INSUFFICIENT_FUNDS_RENEWAL_MSG.format(required_amount=required_amount_text),
|
||||
reply_markup=builder.as_markup(),
|
||||
)
|
||||
return
|
||||
|
||||
except Exception as error:
|
||||
logger.error(f"[ADDONS] PACK_MODE ошибка при покупке пакета для {email}: {error}")
|
||||
await callback.message.answer("❌ Ошибка при обновлении подписки. Попробуйте позже.")
|
||||
await state.clear()
|
||||
try:
|
||||
expiry_time = record["expiry_time"]
|
||||
client_id = record["client_id"]
|
||||
server_id = record["server_id"]
|
||||
|
||||
device_limit_effective_current, traffic_limit_bytes_effective_current = await get_effective_limits_for_key(
|
||||
session=session,
|
||||
tariff_id=int(tariff_id),
|
||||
selected_device_limit=int(current_devices) if current_devices is not None else None,
|
||||
selected_traffic_gb=int(current_traffic_gb) if current_traffic_gb is not None else None,
|
||||
)
|
||||
traffic_limit_gb_effective_current = (
|
||||
int(traffic_limit_bytes_effective_current / GB) if traffic_limit_bytes_effective_current else 0
|
||||
)
|
||||
|
||||
new_device_limit_effective = device_limit_effective_current
|
||||
new_traffic_limit_gb_effective = traffic_limit_gb_effective_current
|
||||
|
||||
if has_device_option and selected_devices is not None:
|
||||
pack_devices_val = int(selected_devices)
|
||||
if pack_devices_val <= 0 or (new_device_limit_effective is not None and new_device_limit_effective <= 0):
|
||||
new_device_limit_effective = 0
|
||||
else:
|
||||
if new_device_limit_effective is None:
|
||||
new_device_limit_effective = pack_devices_val
|
||||
else:
|
||||
new_device_limit_effective = new_device_limit_effective + pack_devices_val
|
||||
|
||||
if has_traffic_option and selected_traffic_gb is not None:
|
||||
pack_traffic_val = int(selected_traffic_gb)
|
||||
if pack_traffic_val <= 0 or new_traffic_limit_gb_effective <= 0:
|
||||
new_traffic_limit_gb_effective = 0
|
||||
else:
|
||||
new_traffic_limit_gb_effective = new_traffic_limit_gb_effective + pack_traffic_val
|
||||
|
||||
current_subgroup = None
|
||||
try:
|
||||
current_tariff_id = record.get("tariff_id")
|
||||
if current_tariff_id:
|
||||
current_tariff = await get_tariff_by_id(session, int(current_tariff_id))
|
||||
if current_tariff:
|
||||
current_subgroup = current_tariff.get("subgroup_title")
|
||||
except Exception as error:
|
||||
logger.warning(f"[ADDONS] PACK_MODE: не удалось определить текущую подгруппу: {error}")
|
||||
|
||||
target_subgroup = tariff.get("subgroup_title")
|
||||
old_subgroup = current_subgroup
|
||||
|
||||
total_gb = new_traffic_limit_gb_effective
|
||||
hwid_device_limit_to_set = new_device_limit_effective
|
||||
|
||||
logger.debug(
|
||||
"[ADDONS] PACK_MODE renew_key_in_cluster params: "
|
||||
f"server_id={server_id} email={email} client_id={client_id} total_gb={total_gb} "
|
||||
f"hwid_device_limit_to_set={hwid_device_limit_to_set} target_subgroup={target_subgroup} "
|
||||
f"old_subgroup={old_subgroup}"
|
||||
)
|
||||
|
||||
await renew_key_in_cluster(
|
||||
cluster_id=server_id,
|
||||
email=email,
|
||||
client_id=client_id,
|
||||
new_expiry_time=expiry_time,
|
||||
total_gb=total_gb,
|
||||
session=session,
|
||||
hwid_device_limit=hwid_device_limit_to_set,
|
||||
reset_traffic=False,
|
||||
target_subgroup=target_subgroup,
|
||||
old_subgroup=old_subgroup,
|
||||
plan=int(tariff_id),
|
||||
)
|
||||
|
||||
result = await session.execute(
|
||||
sa.update(User)
|
||||
.where(User.tg_id == tg_id, User.balance >= extra_price)
|
||||
.values(balance=User.balance - extra_price)
|
||||
)
|
||||
if (result.rowcount or 0) != 1:
|
||||
await session.rollback()
|
||||
await callback.answer("❌ Недостаточно средств.", show_alert=True)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
await save_key_config_with_mode(
|
||||
session=session,
|
||||
email=email,
|
||||
selected_devices=new_device_limit_effective,
|
||||
selected_traffic_gb=new_traffic_limit_gb_effective,
|
||||
total_price=int(total_price_after_purchase),
|
||||
has_device_choice=has_device_option,
|
||||
has_traffic_choice=has_traffic_option,
|
||||
config_mode="pack",
|
||||
)
|
||||
|
||||
await session.commit()
|
||||
|
||||
logger.info(
|
||||
"[ADDONS] PACK_MODE успешная покупка пакета: "
|
||||
f"tg_id={tg_id} email={email} extra_price={extra_price} "
|
||||
f"new_device_limit_effective={new_device_limit_effective} "
|
||||
f"new_traffic_limit_gb_effective={new_traffic_limit_gb_effective} "
|
||||
f"recalc_enabled={recalc_enabled} pack_mode={pack_mode!r}"
|
||||
)
|
||||
|
||||
await state.clear()
|
||||
await render_key_info(callback.message, session, email, "img/pic_view.jpg")
|
||||
await callback.answer(ADDONS_PACK_SUCCESS_TEXT, show_alert=True)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(f"[ADDONS] PACK_MODE ошибка при покупке пакета для {email}: {error}")
|
||||
await callback.message.answer("❌ Ошибка при обновлении подписки. Попробуйте позже.")
|
||||
await state.clear()
|
||||
|
||||
finally:
|
||||
try:
|
||||
await state.update_data(addon_confirm_in_progress=False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user