Initial commit: VPN Telegram bot (sanitized defaults)
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""Лимит устройств (HWID): база 10, каждое сверх — 50 ₽."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
BASE_DEVICES = 10
|
||||
EXTRA_DEVICE_PRICE_RUB = 50.0
|
||||
|
||||
# Сколько устройств панель может зарегистрировать максимум (мягкий потолок).
|
||||
# Реальная квота: BASE_DEVICES + оплаченные слоты; при превышении — DISABLE.
|
||||
PANEL_SOFT_CAP = 100
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class DevicePack:
|
||||
slots: int
|
||||
price: float
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return f"dev_{self.slots}"
|
||||
|
||||
@property
|
||||
def title(self) -> str:
|
||||
return f"+{self.slots} устр."
|
||||
|
||||
def format_price(self) -> str:
|
||||
if self.price == int(self.price):
|
||||
return f"{int(self.price)} ₽/мес"
|
||||
return f"{self.price:.2f} ₽/мес"
|
||||
|
||||
|
||||
DEVICE_PACKS: tuple[DevicePack, ...] = tuple(
|
||||
DevicePack(slots=n, price=EXTRA_DEVICE_PRICE_RUB * n) for n in (1, 2, 3, 5)
|
||||
)
|
||||
|
||||
|
||||
def get_device_pack(pack_id: str) -> DevicePack | None:
|
||||
for p in DEVICE_PACKS:
|
||||
if p.id == pack_id or str(p.slots) == pack_id:
|
||||
return p
|
||||
return None
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class DeviceUsage:
|
||||
used: int
|
||||
allowed: int
|
||||
extra_paid: int
|
||||
over_limit: bool
|
||||
|
||||
@property
|
||||
def excess(self) -> int:
|
||||
return max(0, self.used - self.allowed)
|
||||
|
||||
@property
|
||||
def excess_price(self) -> float:
|
||||
return self.excess * EXTRA_DEVICE_PRICE_RUB
|
||||
|
||||
def format_line(self) -> str:
|
||||
line = (
|
||||
f"📱 Устройства: <b>{self.used} / {self.allowed}</b> "
|
||||
f"(база {BASE_DEVICES}"
|
||||
+ (f" + {self.extra_paid} доп." if self.extra_paid else "")
|
||||
+ ")"
|
||||
)
|
||||
if self.over_limit:
|
||||
line += (
|
||||
f"\n⚠️ Превышение: <b>+{self.excess}</b> · "
|
||||
f"к оплате <b>{int(self.excess_price)} ₽</b>\n"
|
||||
"Подписка отключена, пока не оплатишь лишние устройства "
|
||||
f"({int(EXTRA_DEVICE_PRICE_RUB)} ₽ за каждое)."
|
||||
)
|
||||
return line
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
return {
|
||||
"used": self.used,
|
||||
"allowed": self.allowed,
|
||||
"base": BASE_DEVICES,
|
||||
"extra_paid": self.extra_paid,
|
||||
"over_limit": self.over_limit,
|
||||
"excess": self.excess,
|
||||
"excess_price": self.excess_price,
|
||||
"slot_price": EXTRA_DEVICE_PRICE_RUB,
|
||||
}
|
||||
|
||||
|
||||
def allowed_devices(extra_paid: int) -> int:
|
||||
return BASE_DEVICES + max(0, int(extra_paid or 0))
|
||||
Reference in New Issue
Block a user