month reset

This commit is contained in:
2026-07-10 00:44:42 +03:00
parent cdf380243d
commit 83a6b3fbe6
4 changed files with 15 additions and 6 deletions
+1 -1
View File
@@ -127,7 +127,7 @@ Send it to the user.
"inbounds": {"vless": ["VLESS TCP REALITY"]}, "inbounds": {"vless": ["VLESS TCP REALITY"]},
"expire": "now + 3 days", "expire": "now + 3 days",
"data_limit": "10 GiB", "data_limit": "10 GiB",
"data_limit_reset_strategy": "no_reset", "data_limit_reset_strategy": "month",
"status": "active" "status": "active"
} }
``` ```
+1 -1
View File
@@ -17,7 +17,7 @@ def test_build_trial_user_payload_matches_required_proxy_inbound_and_limits():
assert payload["inbounds"] == {"vless": ["VLESS TCP REALITY"]} assert payload["inbounds"] == {"vless": ["VLESS TCP REALITY"]}
assert payload["expire"] == 1_700_000_000 + 3 * 24 * 60 * 60 assert payload["expire"] == 1_700_000_000 + 3 * 24 * 60 * 60
assert payload["data_limit"] == 10 * GIB assert payload["data_limit"] == 10 * GIB
assert payload["data_limit_reset_strategy"] == "no_reset" assert payload["data_limit_reset_strategy"] == "month"
assert payload["status"] == "active" assert payload["status"] == "active"
assert "Phone: +79990000000" in payload["note"] assert "Phone: +79990000000" in payload["note"]
assert "856850518" not in payload["note"] assert "856850518" not in payload["note"]
+9 -1
View File
@@ -4,6 +4,14 @@ import tomllib
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from urllib.parse import urlsplit, urlunsplit
def normalize_marzban_url(url: str) -> str:
parsed = urlsplit(url.strip().rstrip("/"))
if parsed.scheme and parsed.netloc:
return urlunsplit((parsed.scheme, parsed.netloc, "", "", ""))
return url.strip().rstrip("/")
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -22,7 +30,7 @@ class Config:
return cls( return cls(
telegram_bot_token=str(data["telegram_bot_token"]), telegram_bot_token=str(data["telegram_bot_token"]),
admin_ids={int(item) for item in data.get("admin_ids", [])}, admin_ids={int(item) for item in data.get("admin_ids", [])},
marzban_url=str(data["marzban_url"]).rstrip("/"), marzban_url=normalize_marzban_url(str(data["marzban_url"])),
marzban_username=str(data["marzban_username"]), marzban_username=str(data["marzban_username"]),
marzban_password=str(data["marzban_password"]), marzban_password=str(data["marzban_password"]),
payment_text=str(data["payment_text"]), payment_text=str(data["payment_text"]),
+4 -3
View File
@@ -18,6 +18,7 @@ from .utils import (
DEFAULT_PROXIES = {"vless": {"flow": "xtls-rprx-vision"}} DEFAULT_PROXIES = {"vless": {"flow": "xtls-rprx-vision"}}
DEFAULT_INBOUNDS = {"vless": ["VLESS TCP REALITY"]} DEFAULT_INBOUNDS = {"vless": ["VLESS TCP REALITY"]}
DATA_LIMIT_RESET_STRATEGY = "month"
class MarzbanError(RuntimeError): class MarzbanError(RuntimeError):
@@ -53,7 +54,7 @@ class MarzbanClient:
"inbounds": DEFAULT_INBOUNDS, "inbounds": DEFAULT_INBOUNDS,
"expire": current + TRIAL_DAYS * 24 * 60 * 60, "expire": current + TRIAL_DAYS * 24 * 60 * 60,
"data_limit": TRIAL_TRAFFIC_BYTES, "data_limit": TRIAL_TRAFFIC_BYTES,
"data_limit_reset_strategy": "no_reset", "data_limit_reset_strategy": DATA_LIMIT_RESET_STRATEGY,
"status": "active", "status": "active",
"note": build_marzban_note( "note": build_marzban_note(
first_name=first_name, first_name=first_name,
@@ -128,7 +129,7 @@ class MarzbanClient:
payload = { payload = {
"expire": new_expire, "expire": new_expire,
"data_limit": PAID_TRAFFIC_BYTES, "data_limit": PAID_TRAFFIC_BYTES,
"data_limit_reset_strategy": "no_reset", "data_limit_reset_strategy": DATA_LIMIT_RESET_STRATEGY,
"status": "active", "status": "active",
} }
await self.modify_user(username, payload) await self.modify_user(username, payload)
@@ -141,7 +142,7 @@ class MarzbanClient:
payload = { payload = {
"expire": new_expire, "expire": new_expire,
"data_limit": PAID_TRAFFIC_BYTES, "data_limit": PAID_TRAFFIC_BYTES,
"data_limit_reset_strategy": "no_reset", "data_limit_reset_strategy": DATA_LIMIT_RESET_STRATEGY,
"status": "active", "status": "active",
} }
await self.modify_user(username, payload) await self.modify_user(username, payload)