first init

This commit is contained in:
2026-07-09 23:39:40 +03:00
parent 31281ad8cc
commit cb573a52d5
17 changed files with 1067 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
from pathlib import Path
from vpn_bot.db import Database
def test_invite_is_stored_before_activation_and_can_be_loaded(tmp_path: Path):
db = Database(tmp_path / "bot.sqlite3")
db.init()
db.create_invite(token="abc", admin_id=42, created_at=1000)
user = db.get_by_token("abc")
assert user is not None
assert user["invite_token"] == "abc"
assert user["invite_created_by_admin_id"] == 42
assert user["tg_user_id"] is None
def test_activation_stores_telegram_identity_and_marzban_username(tmp_path: Path):
db = Database(tmp_path / "bot.sqlite3")
db.init()
db.create_invite(token="abc", admin_id=42, created_at=1000)
db.activate_invite(
token="abc",
tg_user_id=856850518,
tg_username="krosh",
tg_first_name="Dmitry",
tg_last_name="Gudov",
tg_phone=None,
marzban_username="tg856850518",
activated_at=1100,
)
user = db.get_by_tg_user_id(856850518)
assert user is not None
assert user["invite_token"] == "abc"
assert user["marzban_username"] == "tg856850518"
assert user["tg_first_name"] == "Dmitry"
def test_used_invite_cannot_be_activated_twice(tmp_path: Path):
db = Database(tmp_path / "bot.sqlite3")
db.init()
db.create_invite(token="abc", admin_id=42, created_at=1000)
db.activate_invite(
token="abc",
tg_user_id=1,
tg_username=None,
tg_first_name="One",
tg_last_name=None,
tg_phone=None,
marzban_username="tg1",
activated_at=1100,
)
try:
db.activate_invite(
token="abc",
tg_user_id=2,
tg_username=None,
tg_first_name="Two",
tg_last_name=None,
tg_phone=None,
marzban_username="tg2",
activated_at=1200,
)
except ValueError as exc:
assert "already used" in str(exc)
else:
raise AssertionError("second activation should fail")
+23
View File
@@ -0,0 +1,23 @@
from vpn_bot.marzban import MarzbanClient
from vpn_bot.utils import GIB
def test_build_trial_user_payload_matches_required_proxy_inbound_and_limits():
payload = MarzbanClient.build_trial_user_payload(
tg_user_id=856850518,
first_name="Dmitry",
last_name="Gudov",
tg_username="krosh",
phone="+79990000000",
now=1_700_000_000,
)
assert payload["username"] == "tg856850518"
assert payload["proxies"] == {"vless": {"flow": "xtls-rprx-vision"}}
assert payload["inbounds"] == {"vless": ["VLESS TCP REALITY"]}
assert payload["expire"] == 1_700_000_000 + 3 * 24 * 60 * 60
assert payload["data_limit"] == 10 * GIB
assert payload["data_limit_reset_strategy"] == "no_reset"
assert payload["status"] == "active"
assert "Phone: +79990000000" in payload["note"]
assert "856850518" not in payload["note"]
+67
View File
@@ -0,0 +1,67 @@
from datetime import datetime, timezone
from vpn_bot.utils import (
GIB,
add_days_from_base,
bytes_to_human,
build_marzban_note,
calculate_reset_expire,
format_marzban_username,
)
def test_format_marzban_username_uses_tg_prefix():
assert format_marzban_username(856850518) == "tg856850518"
def test_build_marzban_note_omits_telegram_id_and_missing_phone():
note = build_marzban_note(
first_name="Dmitry",
last_name="Gudov",
username="dima",
phone=None,
)
assert "First name: Dmitry" in note
assert "Last name: Gudov" in note
assert "Username: @dima" in note
assert "Phone:" not in note
assert "856" not in note
def test_add_days_from_future_expiration_extends_from_future_timestamp():
now = 1_700_000_000
future = now + 2 * 24 * 60 * 60
assert add_days_from_base(current_expire=future, days=30, now=now) == future + 30 * 24 * 60 * 60
def test_add_days_from_expired_account_extends_from_now():
now = 1_700_000_000
expired = now - 10
assert add_days_from_base(current_expire=expired, days=30, now=now) == now + 30 * 24 * 60 * 60
def test_calculate_reset_expire_floors_remaining_time_to_whole_30_day_months():
now = 1_700_000_000
expire = now + (1 * 30 + 12) * 24 * 60 * 60
new_expire, full_months = calculate_reset_expire(expire=expire, now=now)
assert full_months == 1
assert new_expire == now + 30 * 24 * 60 * 60
def test_calculate_reset_expire_discards_partial_month_when_less_than_one_month_left():
now = 1_700_000_000
expire = now + 12 * 24 * 60 * 60
new_expire, full_months = calculate_reset_expire(expire=expire, now=now)
assert full_months == 0
assert new_expire == now
def test_bytes_to_human_formats_gib():
assert bytes_to_human(50 * GIB) == "50.00 GB"