"""Пробный период подписки.""" 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, )