gb_count/fix coupons
This commit is contained in:
@@ -19,7 +19,7 @@ bot = Bot(token=API_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTM
|
||||
storage = MemoryStorage()
|
||||
dp = Dispatcher(bot=bot, storage=storage)
|
||||
|
||||
version = "4.2-alpha(10.04)"
|
||||
version = "4.2-alpha(11.04)"
|
||||
|
||||
register_middleware(dp)
|
||||
|
||||
|
||||
@@ -18,19 +18,12 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from config import INLINE_MODE, USERNAME_BOT
|
||||
from database import (
|
||||
add_connection,
|
||||
check_connection_exists,
|
||||
create_coupon,
|
||||
create_coupon_usage,
|
||||
delete_coupon,
|
||||
get_all_coupons,
|
||||
get_keys,
|
||||
update_key_expiry,
|
||||
)
|
||||
from filters.admin import IsAdminFilter
|
||||
from handlers.buttons import BACK
|
||||
from handlers.keys.key_utils import renew_key_in_cluster
|
||||
from handlers.profile import process_callback_view_profile
|
||||
from handlers.utils import format_days
|
||||
from logger import logger
|
||||
|
||||
@@ -45,7 +38,6 @@ class AdminCouponsState(StatesGroup):
|
||||
waiting_for_coupon_type = State()
|
||||
waiting_for_balance_data = State()
|
||||
waiting_for_days_data = State()
|
||||
waiting_for_key_selection = State()
|
||||
|
||||
|
||||
@router.callback_query(
|
||||
@@ -328,162 +320,4 @@ async def inline_coupon_handler(inline_query: InlineQuery, session: Any):
|
||||
results=[result],
|
||||
cache_time=86400,
|
||||
is_personal=True
|
||||
)
|
||||
|
||||
@router.message(F.text.regexp(r"^/start coupons_(.+)$"))
|
||||
async def handle_coupon_activation(
|
||||
message: Message, state: FSMContext, session: Any, admin: bool = False, text: str = None, user_id: int = None
|
||||
):
|
||||
coupon_text = text if text is not None else message.text
|
||||
logger.info(f"Текст купона в handle_coupon_activation: {coupon_text}")
|
||||
coupon_code = coupon_text.split("coupons_")[1]
|
||||
|
||||
coupons = await get_all_coupons(session, page=1, per_page=10)
|
||||
coupon = next((c for c in coupons["coupons"] if c["code"] == coupon_code), None)
|
||||
|
||||
if not coupon:
|
||||
await message.answer("❌ Купон не найден.")
|
||||
return
|
||||
|
||||
if coupon["usage_count"] >= coupon["usage_limit"] or coupon["is_used"]:
|
||||
await message.answer("❌ Лимит активаций купона исчерпан.")
|
||||
return
|
||||
|
||||
effective_user_id = user_id if user_id is not None else message.from_user.id
|
||||
|
||||
usage = await session.fetchrow(
|
||||
"SELECT * FROM coupon_usages WHERE coupon_id = $1 AND user_id = $2",
|
||||
coupon["id"],
|
||||
effective_user_id
|
||||
)
|
||||
if usage:
|
||||
await message.answer("❌ Вы уже активировали этот купон.")
|
||||
return
|
||||
|
||||
connection_exists = await check_connection_exists(effective_user_id)
|
||||
if not connection_exists:
|
||||
await add_connection(tg_id=effective_user_id, session=session)
|
||||
|
||||
if coupon["amount"] > 0:
|
||||
await session.execute(
|
||||
"UPDATE connections SET balance = balance + $1 WHERE tg_id = $2",
|
||||
coupon["amount"],
|
||||
effective_user_id
|
||||
)
|
||||
await session.execute(
|
||||
"UPDATE coupons SET usage_count = usage_count + 1, is_used = $1 WHERE id = $2",
|
||||
coupon["usage_count"] + 1 >= coupon["usage_limit"],
|
||||
coupon["id"]
|
||||
)
|
||||
await create_coupon_usage(coupon["id"], effective_user_id, session)
|
||||
await message.answer(f"✅ Купон активирован, на баланс начислено {coupon['amount']} рублей.")
|
||||
await process_callback_view_profile(message, state, admin)
|
||||
return
|
||||
|
||||
if coupon["days"] is not None and coupon["days"] > 0:
|
||||
keys = await get_keys(effective_user_id, session)
|
||||
active_keys = [k for k in keys if not k["is_frozen"]]
|
||||
|
||||
if not active_keys:
|
||||
await message.answer("❌ У вас нет активных подписок для продления.")
|
||||
return
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
moscow_tz = pytz.timezone("Europe/Moscow")
|
||||
response_message = "<b>🔑 Выберите подписку для продления:</b>\n\n<blockquote>"
|
||||
|
||||
for key in active_keys:
|
||||
alias = key.get("alias")
|
||||
email = key["email"]
|
||||
client_id = key["client_id"]
|
||||
expiry_time = key.get("expiry_time")
|
||||
|
||||
key_display = html.escape(alias.strip() if alias else email)
|
||||
expiry_date = datetime.fromtimestamp(expiry_time / 1000, tz=moscow_tz).strftime("до %d.%m.%y, %H:%M")
|
||||
response_message += f"• <b>{key_display}</b> ({expiry_date})\n"
|
||||
builder.button(text=key_display, callback_data=f"extend_key|{client_id}|{coupon['id']}")
|
||||
|
||||
response_message += "</blockquote>"
|
||||
builder.button(text="Отмена", callback_data="cancel_coupon_activation")
|
||||
builder.adjust(1)
|
||||
|
||||
await message.answer(response_message, reply_markup=builder.as_markup())
|
||||
await state.set_state(AdminCouponsState.waiting_for_key_selection)
|
||||
await state.update_data(coupon_id=coupon["id"], user_id=effective_user_id)
|
||||
return
|
||||
|
||||
await message.answer("❌ Купон недействителен (нет суммы или дней).")
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("extend_key|"))
|
||||
async def handle_key_extension(callback_query: CallbackQuery, state: FSMContext, session: Any, admin: bool = False):
|
||||
parts = callback_query.data.split("|")
|
||||
client_id = parts[1]
|
||||
coupon_id = int(parts[2])
|
||||
|
||||
coupon = await session.fetchrow("SELECT * FROM coupons WHERE id = $1", coupon_id)
|
||||
if not coupon or coupon["usage_count"] >= coupon["usage_limit"]:
|
||||
await callback_query.message.edit_text("❌ Купон недействителен или лимит исчерпан.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
usage = await session.fetchrow(
|
||||
"SELECT * FROM coupon_usages WHERE coupon_id = $1 AND user_id = $2",
|
||||
coupon_id,
|
||||
callback_query.from_user.id
|
||||
)
|
||||
if usage:
|
||||
await callback_query.message.edit_text("❌ Вы уже активировали этот купон.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
key = await session.fetchrow(
|
||||
"SELECT * FROM keys WHERE tg_id = $1 AND client_id = $2",
|
||||
callback_query.from_user.id,
|
||||
client_id
|
||||
)
|
||||
if not key or key["is_frozen"]:
|
||||
await callback_query.message.edit_text("❌ Выбранная подписка не найдена или заморожена.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
now_ms = int(datetime.now().timestamp() * 1000)
|
||||
current_expiry = key["expiry_time"]
|
||||
new_expiry = max(now_ms, current_expiry) + (coupon["days"] * 86400 * 1000)
|
||||
|
||||
try:
|
||||
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
|
||||
)
|
||||
await update_key_expiry(client_id, new_expiry, session)
|
||||
|
||||
await session.execute(
|
||||
"UPDATE coupons SET usage_count = usage_count + 1, is_used = $1 WHERE id = $2",
|
||||
coupon["usage_count"] + 1 >= coupon["usage_limit"],
|
||||
coupon["id"]
|
||||
)
|
||||
await create_coupon_usage(coupon["id"], callback_query.from_user.id, session)
|
||||
|
||||
alias = key.get("alias") or key["email"]
|
||||
expiry_date = datetime.fromtimestamp(new_expiry / 1000, tz=pytz.timezone("Europe/Moscow")).strftime("%d.%m.%y, %H:%M")
|
||||
text = f"✅ Купон активирован, подписка <b>{alias}</b> продлена на {format_days(coupon['days'])}⏳ до {expiry_date}📆."
|
||||
|
||||
await callback_query.message.answer(text)
|
||||
await process_callback_view_profile(callback_query.message, state, admin)
|
||||
await state.clear()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при продлении ключа: {e}")
|
||||
await callback_query.message.edit_text("❌ Произошла ошибка при продлении подписки.")
|
||||
await state.clear()
|
||||
|
||||
|
||||
@router.callback_query(F.data == "cancel_coupon_activation")
|
||||
async def cancel_coupon_activation(callback_query: CallbackQuery, state: FSMContext, admin: bool = False):
|
||||
await callback_query.message.answer("⚠️ Активация купона отменена.")
|
||||
await process_callback_view_profile(callback_query.message, state, admin)
|
||||
await state.clear()
|
||||
)
|
||||
+153
-23
@@ -5,27 +5,36 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
import pytz
|
||||
import html
|
||||
from datetime import datetime
|
||||
|
||||
from database import (
|
||||
check_coupon_usage,
|
||||
create_coupon_usage,
|
||||
get_coupon_by_code,
|
||||
get_keys,
|
||||
update_balance,
|
||||
update_coupon_usage_count,
|
||||
update_key_expiry,
|
||||
check_connection_exists,
|
||||
add_connection,
|
||||
)
|
||||
from handlers.buttons import MAIN_MENU, COUPON_RESTART
|
||||
from handlers.buttons import MAIN_MENU
|
||||
from handlers.keys.key_utils import renew_key_in_cluster
|
||||
from handlers.texts import (
|
||||
COUPON_ACTIVATED_SUCCESS_MSG,
|
||||
COUPON_ALREADY_USED_MSG,
|
||||
COUPON_INPUT_PROMPT,
|
||||
COUPON_NOT_FOUND_MSG,
|
||||
)
|
||||
|
||||
from .utils import edit_or_send_message
|
||||
from handlers.utils import edit_or_send_message, format_days
|
||||
from handlers.profile import process_callback_view_profile
|
||||
from logger import logger
|
||||
|
||||
|
||||
class CouponActivationState(StatesGroup):
|
||||
waiting_for_coupon_code = State()
|
||||
waiting_for_key_selection = State()
|
||||
|
||||
|
||||
router = Router()
|
||||
@@ -54,32 +63,153 @@ async def handle_activate_coupon(callback_query_or_message: Message | CallbackQu
|
||||
@router.message(CouponActivationState.waiting_for_coupon_code)
|
||||
async def process_coupon_code(message: Message, state: FSMContext, session: Any):
|
||||
coupon_code = message.text.strip()
|
||||
activation_result = await activate_coupon(message.chat.id, coupon_code, session)
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
builder.row(InlineKeyboardButton(text=COUPON_RESTART, callback_data="activate_coupon"))
|
||||
|
||||
await message.answer(activation_result, reply_markup=builder.as_markup())
|
||||
|
||||
await state.clear()
|
||||
await activate_coupon(message, state, session, coupon_code=coupon_code)
|
||||
|
||||
|
||||
async def activate_coupon(user_id: int, coupon_code: str, session: Any):
|
||||
async def activate_coupon(
|
||||
message: Message, state: FSMContext, session: Any, coupon_code: str, admin: bool = False
|
||||
):
|
||||
logger.info(f"Активация купона: {coupon_code}")
|
||||
coupon_record = await get_coupon_by_code(coupon_code, session)
|
||||
|
||||
if not coupon_record:
|
||||
return COUPON_NOT_FOUND_MSG
|
||||
await message.answer(COUPON_NOT_FOUND_MSG)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
usage_exists = await check_coupon_usage(coupon_record["id"], user_id, session)
|
||||
if coupon_record["usage_count"] >= coupon_record["usage_limit"] or coupon_record["is_used"]:
|
||||
await message.answer("❌ Лимит активаций купона исчерпан.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
if usage_exists:
|
||||
return COUPON_ALREADY_USED_MSG
|
||||
user_id = message.chat.id
|
||||
|
||||
coupon_amount = coupon_record["amount"]
|
||||
usage = await check_coupon_usage(coupon_record["id"], user_id, session)
|
||||
if usage:
|
||||
await message.answer(COUPON_ALREADY_USED_MSG)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
await update_coupon_usage_count(coupon_record["id"], session)
|
||||
await create_coupon_usage(coupon_record["id"], user_id, session)
|
||||
connection_exists = await check_connection_exists(user_id)
|
||||
if not connection_exists:
|
||||
await add_connection(tg_id=user_id, session=session)
|
||||
|
||||
await update_balance(user_id, coupon_amount, session)
|
||||
return COUPON_ACTIVATED_SUCCESS_MSG.format(coupon_amount=coupon_amount)
|
||||
if coupon_record["amount"] > 0:
|
||||
try:
|
||||
await update_balance(user_id, coupon_record["amount"], session, skip_referral=True)
|
||||
await update_coupon_usage_count(coupon_record["id"], session)
|
||||
await create_coupon_usage(coupon_record["id"], user_id, session)
|
||||
await message.answer(f"✅ Купон активирован, на баланс начислено {coupon_record['amount']} рублей.")
|
||||
await process_callback_view_profile(message, state, admin)
|
||||
await state.clear()
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при активации купона на баланс: {e}")
|
||||
await message.answer("❌ Ошибка при активации купона.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
if coupon_record["days"] is not None and coupon_record["days"] > 0:
|
||||
try:
|
||||
keys = await get_keys(user_id, session)
|
||||
active_keys = [k for k in keys if not k["is_frozen"]]
|
||||
|
||||
if not active_keys:
|
||||
await message.answer("❌ У вас нет активных подписок для продления.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
moscow_tz = pytz.timezone("Europe/Moscow")
|
||||
response_message = "<b>🔑 Выберите подписку для продления:</b>\n\n<blockquote>"
|
||||
|
||||
for key in active_keys:
|
||||
alias = key.get("alias")
|
||||
email = key["email"]
|
||||
client_id = key["client_id"]
|
||||
expiry_time = key.get("expiry_time")
|
||||
|
||||
key_display = html.escape(alias.strip() if alias else email)
|
||||
expiry_date = datetime.fromtimestamp(expiry_time / 1000, tz=moscow_tz).strftime("до %d.%m.%y, %H:%M")
|
||||
response_message += f"• <b>{key_display}</b> ({expiry_date})\n"
|
||||
builder.button(text=key_display, callback_data=f"extend_key|{client_id}|{coupon_record['id']}")
|
||||
|
||||
response_message += "</blockquote>"
|
||||
builder.button(text="Отмена", callback_data="cancel_coupon_activation")
|
||||
builder.adjust(1)
|
||||
|
||||
await message.answer(response_message, reply_markup=builder.as_markup())
|
||||
await state.set_state(CouponActivationState.waiting_for_key_selection)
|
||||
await state.update_data(coupon_id=coupon_record["id"], user_id=user_id)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обработке купона на дни: {e}")
|
||||
await message.answer("❌ Ошибка при активации купона.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
await message.answer("❌ Купон недействителен (нет суммы или дней).")
|
||||
await state.clear()
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("extend_key|"))
|
||||
async def handle_key_extension(callback_query: CallbackQuery, state: FSMContext, session: Any, admin: bool = False):
|
||||
parts = callback_query.data.split("|")
|
||||
client_id = parts[1]
|
||||
coupon_id = int(parts[2])
|
||||
|
||||
try:
|
||||
coupon = await session.fetchrow("SELECT * FROM coupons WHERE id = $1", coupon_id)
|
||||
if not coupon or coupon["usage_count"] >= coupon["usage_limit"]:
|
||||
await callback_query.message.edit_text("❌ Купон недействителен или лимит исчерпан.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
usage = await check_coupon_usage(coupon_id, callback_query.from_user.id, session)
|
||||
if usage:
|
||||
await callback_query.message.edit_text("❌ Вы уже активировали этот купон.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
key = await session.fetchrow(
|
||||
"SELECT * FROM keys WHERE tg_id = $1 AND client_id = $2",
|
||||
callback_query.from_user.id,
|
||||
client_id
|
||||
)
|
||||
if not key or key["is_frozen"]:
|
||||
await callback_query.message.edit_text("❌ Выбранная подписка не найдена или заморожена.")
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
now_ms = int(datetime.now().timestamp() * 1000)
|
||||
current_expiry = key["expiry_time"]
|
||||
new_expiry = max(now_ms, current_expiry) + (coupon["days"] * 86400 * 1000)
|
||||
|
||||
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
|
||||
)
|
||||
await update_key_expiry(client_id, new_expiry, session)
|
||||
|
||||
await update_coupon_usage_count(coupon["id"], session)
|
||||
await create_coupon_usage(coupon["id"], callback_query.from_user.id, session)
|
||||
|
||||
alias = key.get("alias") or key["email"]
|
||||
expiry_date = datetime.fromtimestamp(new_expiry / 1000, tz=pytz.timezone("Europe/Moscow")).strftime("%d.%m.%y, %H:%M")
|
||||
await callback_query.message.answer(
|
||||
f"✅ Купон активирован, подписка <b>{alias}</b> продлена на {format_days(coupon['days'])}⏳ до {expiry_date}📆."
|
||||
)
|
||||
await process_callback_view_profile(callback_query.message, state, admin)
|
||||
await state.clear()
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при продлении ключа: {e}")
|
||||
await callback_query.message.edit_text("❌ Ошибка при активации купона.")
|
||||
await state.clear()
|
||||
|
||||
|
||||
@router.callback_query(F.data == "cancel_coupon_activation")
|
||||
async def cancel_coupon_activation(callback_query: CallbackQuery, state: FSMContext, admin: bool = False):
|
||||
await callback_query.message.edit_text("⚠️ Активация купона отменена.")
|
||||
await process_callback_view_profile(callback_query.message, state, admin)
|
||||
await state.clear()
|
||||
+11
-37
@@ -106,8 +106,7 @@ async def process_callback_renew_plan(callback_query: CallbackQuery, session: An
|
||||
plan, client_id = callback_query.data.split("|")[1], callback_query.data.split("|")[2]
|
||||
days_to_extend = 30 * int(plan)
|
||||
|
||||
gb_multiplier = {"1": 1, "3": 3, "6": 6, "12": 12}
|
||||
total_gb = TOTAL_GB * gb_multiplier.get(plan, 1) if TOTAL_GB > 0 else 0
|
||||
total_gb = int((int(plan) or 1) * TOTAL_GB * 1024**3)
|
||||
|
||||
try:
|
||||
record = await get_key_by_server(tg_id, client_id, session)
|
||||
@@ -178,17 +177,11 @@ async def process_callback_renew_plan(callback_query: CallbackQuery, session: An
|
||||
|
||||
|
||||
async def complete_key_renewal(tg_id, client_id, email, new_expiry_time, total_gb, cost, callback_query, plan):
|
||||
logger.info(
|
||||
f"[RENEW] Начинаю процесс продления ключа с параметрами: "
|
||||
f"tg_id={tg_id}, client_id={client_id}, email={email}, "
|
||||
f"new_expiry_time={new_expiry_time}, total_gb={total_gb}, cost={cost}, "
|
||||
f"callback_query={'есть' if callback_query else 'отсутствует'}, plan={plan}"
|
||||
)
|
||||
|
||||
response_message = SUCCESS_RENEWAL_MSG.format(months=plan)
|
||||
logger.info(f"[Info] Продление ключа {client_id} на {plan} мес. (Start)")
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.row(InlineKeyboardButton(text=MAIN_MENU, callback_data="profile"))
|
||||
response_message = SUCCESS_RENEWAL_MSG.format(months=plan)
|
||||
|
||||
if callback_query:
|
||||
try:
|
||||
@@ -199,52 +192,33 @@ async def complete_key_renewal(tg_id, client_id, email, new_expiry_time, total_g
|
||||
media_path=None,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка редактирования сообщения в complete_key_renewal: {e}")
|
||||
logger.error(f"[Error] Ошибка при редактировании сообщения: {e}")
|
||||
await callback_query.message.answer(response_message, reply_markup=builder.as_markup())
|
||||
else:
|
||||
await bot.send_message(tg_id, response_message, reply_markup=builder.as_markup())
|
||||
|
||||
conn = await asyncpg.connect(DATABASE_URL)
|
||||
|
||||
logger.info(f"[RENEW] Получение данных о ключе для email: {email}")
|
||||
key_info = await get_key_details(email, conn)
|
||||
if not key_info:
|
||||
logger.error(f"[RENEW] Ключ с client_id {client_id} для пользователя {tg_id} не найден.")
|
||||
logger.error(f"[Error] Ключ с client_id={client_id} не найден в БД.")
|
||||
await conn.close()
|
||||
return
|
||||
|
||||
server_id = key_info["server_id"]
|
||||
|
||||
if USE_COUNTRY_SELECTION:
|
||||
logger.info(f"[RENEW] USE_COUNTRY_SELECTION включён. Проверяю информацию о сервере {server_id}")
|
||||
cluster_info = await check_server_name_by_cluster(server_id, conn)
|
||||
if not cluster_info:
|
||||
logger.error(f"[RENEW] Сервер {server_id} не найден в таблице servers.")
|
||||
logger.error(f"[Error] Сервер {server_id} не найден в таблице servers.")
|
||||
await conn.close()
|
||||
return
|
||||
cluster_id = cluster_info["cluster_name"]
|
||||
logger.info(f"[RENEW] Информация о сервере получена: {cluster_info}. Использую cluster_id: {cluster_id}")
|
||||
else:
|
||||
cluster_id = server_id
|
||||
logger.info(f"[RENEW] USE_COUNTRY_SELECTION выключен. Использую server_id в качестве cluster_id: {cluster_id}")
|
||||
|
||||
logger.info(f"[RENEW] Запуск продления ключа для пользователя {tg_id} на {plan} мес. в кластере {cluster_id}.")
|
||||
|
||||
async def renew_key_on_cluster():
|
||||
logger.info(
|
||||
f"[RENEW] Запуск renew_key_on_cluster с параметрами: "
|
||||
f"cluster_id={cluster_id}, email={email}, client_id={client_id}, "
|
||||
f"new_expiry_time={new_expiry_time}, total_gb={total_gb}"
|
||||
)
|
||||
await renew_key_in_cluster(cluster_id, email, client_id, new_expiry_time, total_gb)
|
||||
logger.info("[RENEW] Продление ключа на сервере завершено. Обновляю срок действия в базе данных.")
|
||||
await update_key_expiry(client_id, new_expiry_time, conn)
|
||||
logger.info("[RENEW] Срок действия ключа обновлён. Обновляю баланс пользователя.")
|
||||
await update_balance(tg_id, -cost, conn)
|
||||
logger.info(f"[RENEW] Ключ {client_id} успешно продлён на {plan} мес. для пользователя {tg_id}.")
|
||||
|
||||
logger.info("[RENEW] Инициализация процесса продления ключа в кластере.")
|
||||
await renew_key_on_cluster()
|
||||
|
||||
logger.info("[RENEW] Процесс продления ключа завершён. Закрываю соединение с базой данных.")
|
||||
await renew_key_in_cluster(cluster_id, email, client_id, new_expiry_time, total_gb)
|
||||
await update_key_expiry(client_id, new_expiry_time, conn)
|
||||
await update_balance(tg_id, -cost, conn)
|
||||
await conn.close()
|
||||
|
||||
logger.info(f"[Info] Продление ключа {client_id} завершено успешно (User: {tg_id})")
|
||||
|
||||
@@ -258,6 +258,7 @@ async def renew_key_in_cluster(cluster_id, email, client_id, new_expiry_time, to
|
||||
uuid=client_id,
|
||||
expire_at=expire_iso,
|
||||
active_user_inbounds=remnawave_inbound_ids,
|
||||
traffic_limit_bytes=total_gb
|
||||
)
|
||||
if updated:
|
||||
logger.info(f"Подписка Remnawave {client_id} успешно продлена")
|
||||
|
||||
+4
-4
@@ -31,7 +31,6 @@ from database import (
|
||||
get_trial,
|
||||
update_balance,
|
||||
)
|
||||
from handlers.admin.coupons.coupons_handler import handle_coupon_activation
|
||||
from handlers.buttons import ABOUT_VPN, BACK, CHANNEL, MAIN_MENU, SUPPORT
|
||||
from handlers.captcha import generate_captcha
|
||||
from handlers.keys.key_mode.key_create import create_key
|
||||
@@ -48,6 +47,7 @@ from handlers.texts import (
|
||||
get_about_vpn,
|
||||
)
|
||||
from logger import logger
|
||||
from handlers.coupons import activate_coupon
|
||||
|
||||
from .admin.panel.keyboard import AdminPanelCallback
|
||||
from .utils import edit_or_send_message
|
||||
@@ -119,8 +119,8 @@ async def process_start_logic(
|
||||
try:
|
||||
if "coupons_" in text:
|
||||
logger.info(f"Обнаружена ссылка на купон: {text}")
|
||||
user_id = message.chat.id
|
||||
await handle_coupon_activation(message, state, session, admin, text=text, user_id=user_id)
|
||||
coupon_code = text.split("coupons_")[1]
|
||||
await activate_coupon(message, state, session, coupon_code=coupon_code, admin=admin)
|
||||
return
|
||||
|
||||
if "gift_" in text:
|
||||
@@ -320,4 +320,4 @@ async def handle_about_vpn(callback_query: CallbackQuery):
|
||||
reply_markup=builder.as_markup(),
|
||||
media_path=None,
|
||||
force_text=False,
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user