100 lines
2.9 KiB
Python
100 lines
2.9 KiB
Python
"""Пробный период подписки."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from remnawave import RemnawaveSDK
|
|
|
|
from services.db import AuthError, Database
|
|
from services.purchase import provision_subscription
|
|
from services.tariffs import Tariff, get_tariff
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULT_TRIAL_DAYS = 3
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class TrialResult:
|
|
ok: bool
|
|
message: str
|
|
expire_at: datetime | None = None
|
|
|
|
|
|
def trial_days_setting(db: Database) -> int:
|
|
raw = (db.get_setting("trial_days") or str(DEFAULT_TRIAL_DAYS)).strip()
|
|
try:
|
|
days = int(raw)
|
|
except ValueError:
|
|
days = DEFAULT_TRIAL_DAYS
|
|
return max(0, min(days, 30))
|
|
|
|
|
|
def trial_enabled(db: Database) -> bool:
|
|
return trial_days_setting(db) > 0
|
|
|
|
|
|
async def grant_trial(
|
|
*,
|
|
db: Database,
|
|
sdk: RemnawaveSDK,
|
|
telegram_id: int,
|
|
tariffs: list[Tariff],
|
|
) -> TrialResult:
|
|
days = trial_days_setting(db)
|
|
if days <= 0:
|
|
return TrialResult(ok=False, message="Пробный период выключен")
|
|
|
|
user = db.ensure_user(telegram_id)
|
|
if user.banned:
|
|
return TrialResult(ok=False, message="Аккаунт заблокирован")
|
|
if user.trial_used_at:
|
|
return TrialResult(ok=False, message="Пробный период уже использован")
|
|
|
|
tariff_id = (db.get_setting("trial_tariff_id") or "").strip()
|
|
tariff = get_tariff(tariffs, tariff_id) if tariff_id else None
|
|
if tariff is None and tariffs:
|
|
tariff = min(tariffs, key=lambda t: t.price)
|
|
if tariff is None:
|
|
return TrialResult(ok=False, message="Нет тарифа для пробного периода")
|
|
|
|
trial_tariff = Tariff(
|
|
id=tariff.id,
|
|
title=f"Trial · {tariff.title}",
|
|
price=0.0,
|
|
days=days,
|
|
traffic_gb=tariff.traffic_gb,
|
|
device_limit=tariff.device_limit,
|
|
squad_uuids=tariff.squad_uuids,
|
|
description="trial",
|
|
)
|
|
|
|
try:
|
|
rw_uuid, sub_url, expire_at = await provision_subscription(
|
|
sdk,
|
|
telegram_id=telegram_id,
|
|
tariff=trial_tariff,
|
|
login=user.login,
|
|
extra_devices=user.extra_devices,
|
|
)
|
|
except Exception as exc: # noqa: BLE001
|
|
logger.exception("trial provision failed")
|
|
return TrialResult(ok=False, message=f"Не удалось выдать пробный период: {exc}")
|
|
|
|
db.mark_trial_used(telegram_id)
|
|
db.record_purchase(
|
|
telegram_id,
|
|
tariff_id=f"trial:{tariff.id}",
|
|
price=0.0,
|
|
remnawave_uuid=rw_uuid,
|
|
subscription_url=sub_url,
|
|
)
|
|
return TrialResult(
|
|
ok=True,
|
|
message=f"Пробный период на {days} дн. активен до {expire_at.strftime('%d.%m.%Y %H:%M UTC')}",
|
|
expire_at=expire_at,
|
|
)
|