246 lines
8.3 KiB
Python
246 lines
8.3 KiB
Python
import time
|
||
from typing import Any
|
||
|
||
from aiogram import F, Router
|
||
from aiogram.types import CallbackQuery, InlineKeyboardButton
|
||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||
from sqlalchemy import text
|
||
|
||
from database import get_key_details, mark_key_as_frozen, mark_key_as_unfrozen
|
||
from handlers.buttons import APPLY, BACK, CANCEL
|
||
from handlers.keys.key_utils import renew_key_in_cluster, toggle_client_on_cluster
|
||
from handlers.texts import (
|
||
FREEZE_SUBSCRIPTION_CONFIRM_MSG,
|
||
SUBSCRIPTION_FROZEN_MSG,
|
||
SUBSCRIPTION_UNFROZEN_MSG,
|
||
UNFREEZE_SUBSCRIPTION_CONFIRM_MSG,
|
||
)
|
||
from handlers.utils import edit_or_send_message, handle_error
|
||
from logger import logger
|
||
|
||
router = Router()
|
||
|
||
|
||
@router.callback_query(F.data.startswith("unfreeze_subscription|"))
|
||
async def process_callback_unfreeze_subscription(
|
||
callback_query: CallbackQuery, session: Any
|
||
):
|
||
key_name = callback_query.data.split("|")[1]
|
||
confirm_text = UNFREEZE_SUBSCRIPTION_CONFIRM_MSG
|
||
|
||
builder = InlineKeyboardBuilder()
|
||
builder.row(
|
||
InlineKeyboardButton(
|
||
text=APPLY,
|
||
callback_data=f"unfreeze_subscription_confirm|{key_name}",
|
||
),
|
||
InlineKeyboardButton(
|
||
text=CANCEL,
|
||
callback_data=f"view_key|{key_name}",
|
||
),
|
||
)
|
||
|
||
await edit_or_send_message(
|
||
target_message=callback_query.message,
|
||
text=confirm_text,
|
||
reply_markup=builder.as_markup(),
|
||
)
|
||
|
||
|
||
@router.callback_query(F.data.startswith("unfreeze_subscription_confirm|"))
|
||
async def process_callback_unfreeze_subscription_confirm(
|
||
callback_query: CallbackQuery, session: Any
|
||
):
|
||
"""
|
||
Размораживает (включает) подписку.
|
||
"""
|
||
tg_id = callback_query.message.chat.id
|
||
key_name = callback_query.data.split("|")[1]
|
||
|
||
try:
|
||
record = await get_key_details(session, key_name)
|
||
if not record:
|
||
await callback_query.message.answer("Ключ не найден.")
|
||
return
|
||
|
||
email = record["email"]
|
||
client_id = record["client_id"]
|
||
cluster_id = record["server_id"]
|
||
|
||
result = await toggle_client_on_cluster(
|
||
cluster_id, email, client_id, enable=True, session=session
|
||
)
|
||
if result["status"] != "success":
|
||
text_error = f"Произошла ошибка при включении подписки.\nДетали: {result.get('error') or result.get('results')}"
|
||
builder = InlineKeyboardBuilder()
|
||
builder.row(
|
||
InlineKeyboardButton(text=BACK, callback_data=f"view_key|{key_name}")
|
||
)
|
||
await edit_or_send_message(
|
||
callback_query.message, text_error, builder.as_markup()
|
||
)
|
||
return
|
||
|
||
now_ms = int(time.time() * 1000)
|
||
leftover = record["expiry_time"]
|
||
logger.info(f"[Unfreeze Debug] expiry_time из БД: {leftover}")
|
||
if leftover < 0:
|
||
leftover = 0
|
||
new_expiry_time = now_ms + leftover
|
||
|
||
await mark_key_as_unfrozen(session, record["tg_id"], client_id, new_expiry_time)
|
||
await session.commit()
|
||
|
||
from database.servers import get_servers
|
||
|
||
servers = await get_servers(session)
|
||
cluster_servers = servers.get(cluster_id, [])
|
||
|
||
tariff = None
|
||
for srv in cluster_servers:
|
||
result = await session.execute(
|
||
text(
|
||
"""
|
||
SELECT t.*
|
||
FROM tariffs t
|
||
JOIN servers s ON s.tariff_group = t.group_code
|
||
WHERE s.server_name = :server_name
|
||
ORDER BY t.duration_days DESC
|
||
LIMIT 1
|
||
"""
|
||
),
|
||
{"server_name": srv["server_name"]},
|
||
)
|
||
row = result.mappings().first()
|
||
if row:
|
||
tariff = row
|
||
break
|
||
|
||
await session.commit()
|
||
|
||
if not tariff:
|
||
logger.info(
|
||
"[Unfreeze] Тариф не найден — возможно ключ триальный. Применяем дефолтные значения."
|
||
)
|
||
base_bytes = 15 * 1024
|
||
hwid_limit = 1
|
||
else:
|
||
base_bytes = int(tariff.get("traffic_limit") or 0)
|
||
hwid_limit = int(tariff.get("device_limit") or 0)
|
||
|
||
added_days = max(leftover / (1000 * 86400), 0.01)
|
||
total_gb = int((added_days / 30) * base_bytes)
|
||
logger.info(
|
||
f"[Unfreeze Debug] Запуск renew_key_in_cluster с expiry={new_expiry_time}, gb={total_gb}, hwid={hwid_limit}"
|
||
)
|
||
|
||
await renew_key_in_cluster(
|
||
cluster_id=cluster_id,
|
||
email=email,
|
||
client_id=client_id,
|
||
new_expiry_time=new_expiry_time,
|
||
total_gb=total_gb,
|
||
session=session,
|
||
hwid_device_limit=hwid_limit,
|
||
)
|
||
|
||
text_ok = SUBSCRIPTION_UNFROZEN_MSG
|
||
builder = InlineKeyboardBuilder()
|
||
builder.row(
|
||
InlineKeyboardButton(text=BACK, callback_data=f"view_key|{key_name}")
|
||
)
|
||
await edit_or_send_message(callback_query.message, text_ok, builder.as_markup())
|
||
|
||
except Exception as e:
|
||
await handle_error(tg_id, callback_query, f"Ошибка при включении подписки: {e}")
|
||
|
||
|
||
@router.callback_query(F.data.startswith("freeze_subscription|"))
|
||
async def process_callback_freeze_subscription(
|
||
callback_query: CallbackQuery, session: Any
|
||
):
|
||
"""
|
||
Показывает пользователю диалог подтверждения заморозки (отключения) подписки.
|
||
"""
|
||
key_name = callback_query.data.split("|")[1]
|
||
|
||
confirm_text = FREEZE_SUBSCRIPTION_CONFIRM_MSG
|
||
|
||
builder = InlineKeyboardBuilder()
|
||
builder.row(
|
||
InlineKeyboardButton(
|
||
text=APPLY,
|
||
callback_data=f"freeze_subscription_confirm|{key_name}",
|
||
),
|
||
InlineKeyboardButton(
|
||
text=CANCEL,
|
||
callback_data=f"view_key|{key_name}",
|
||
),
|
||
)
|
||
|
||
await edit_or_send_message(
|
||
target_message=callback_query.message,
|
||
text=confirm_text,
|
||
reply_markup=builder.as_markup(),
|
||
)
|
||
|
||
|
||
@router.callback_query(F.data.startswith("freeze_subscription_confirm|"))
|
||
async def process_callback_freeze_subscription_confirm(
|
||
callback_query: CallbackQuery, session: Any
|
||
):
|
||
"""
|
||
Замораживает (отключает) подписку.
|
||
"""
|
||
tg_id = callback_query.message.chat.id
|
||
key_name = callback_query.data.split("|")[1]
|
||
|
||
try:
|
||
record = await get_key_details(session, key_name)
|
||
if not record:
|
||
await callback_query.message.answer("Ключ не найден.")
|
||
return
|
||
|
||
email = record["email"]
|
||
client_id = record["client_id"]
|
||
cluster_id = record["server_id"]
|
||
|
||
result = await toggle_client_on_cluster(
|
||
cluster_id, email, client_id, enable=False, session=session
|
||
)
|
||
|
||
if result["status"] == "success":
|
||
now_ms = int(time.time() * 1000)
|
||
time_left = record["expiry_time"] - now_ms
|
||
if time_left < 0:
|
||
time_left = 0
|
||
|
||
await mark_key_as_frozen(session, record["tg_id"], client_id, time_left)
|
||
await session.commit()
|
||
|
||
text_ok = SUBSCRIPTION_FROZEN_MSG
|
||
builder = InlineKeyboardBuilder()
|
||
builder.row(
|
||
InlineKeyboardButton(text=BACK, callback_data=f"view_key|{key_name}")
|
||
)
|
||
await edit_or_send_message(
|
||
target_message=callback_query.message,
|
||
text=text_ok,
|
||
reply_markup=builder.as_markup(),
|
||
)
|
||
|
||
else:
|
||
text_error = f"Произошла ошибка при заморозке подписки.\nДетали: {result.get('error') or result.get('results')}"
|
||
builder = InlineKeyboardBuilder()
|
||
builder.row(
|
||
InlineKeyboardButton(text=BACK, callback_data=f"view_key|{key_name}")
|
||
)
|
||
await edit_or_send_message(
|
||
target_message=callback_query.message,
|
||
text=text_error,
|
||
reply_markup=builder.as_markup(),
|
||
)
|
||
|
||
except Exception as e:
|
||
await handle_error(tg_id, callback_query, f"Ошибка при заморозке подписки: {e}")
|