fix: dynamic days remaining via tariff_end_at timestamp; auto-downgrade when expired
This commit is contained in:
+34
-16
@@ -81,6 +81,12 @@ def clear_cache(sub_id: str = None):
|
||||
_links_cache.clear()
|
||||
_traffic_cache.clear()
|
||||
|
||||
def get_remaining_days(user: dict) -> int:
|
||||
end = user.get("tariff_end_at", 0)
|
||||
if end:
|
||||
return max(0, (end - int(time.time())) // 86400)
|
||||
return user.get("tariff_days_remaining", 0)
|
||||
|
||||
def load_json(path: str, default: dict) -> dict:
|
||||
if os.path.exists(path):
|
||||
try:
|
||||
@@ -107,12 +113,19 @@ def init_db():
|
||||
tier TEXT DEFAULT 'free',
|
||||
tariff_days_bought INTEGER DEFAULT 0,
|
||||
tariff_days_remaining INTEGER DEFAULT 0,
|
||||
tariff_end_at INTEGER DEFAULT 0,
|
||||
total_paid_rubles INTEGER DEFAULT 0,
|
||||
traffic_limit_gb INTEGER DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
try:
|
||||
conn.execute("ALTER TABLE users ADD COLUMN tariff_end_at INTEGER DEFAULT 0")
|
||||
except:
|
||||
pass
|
||||
now = int(time.time())
|
||||
conn.execute("UPDATE users SET tariff_end_at = ? + tariff_days_remaining * 86400 WHERE tariff_end_at = 0 AND tariff_days_remaining > 0", (now,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -376,7 +389,7 @@ VALUES (?, ?, 'free', 0, 0, 0, 0, 1)
|
||||
|
||||
user = dict(user)
|
||||
|
||||
if user['tier'] == 'paid' and user['tariff_days_remaining'] <= 0:
|
||||
if user['tier'] == 'paid' and get_remaining_days(user) <= 0:
|
||||
conn.execute("UPDATE users SET tier = 'free' WHERE id = ?", (user['id'],))
|
||||
conn.commit()
|
||||
user['tier'] = 'free'
|
||||
@@ -554,8 +567,9 @@ async def get_subscription(request: Request, subscription_id: str, format: str =
|
||||
lines.append(f"#support-url: {support_url}")
|
||||
|
||||
expire_ts = 0
|
||||
if user.get("tariff_days_remaining", 0) > 0:
|
||||
expire_ts = int((datetime.now() + timedelta(days=user["tariff_days_remaining"])).timestamp())
|
||||
rem_days = get_remaining_days(user)
|
||||
if rem_days > 0:
|
||||
expire_ts = int((datetime.now() + timedelta(days=rem_days)).timestamp())
|
||||
lines.append("#sub-expire: 1")
|
||||
if support_url:
|
||||
lines.append(f"#sub-expire-button-link: {support_url}")
|
||||
@@ -624,7 +638,7 @@ async def get_web_page(subscription_id: str):
|
||||
tier_name = tier_config.get("name", "Free")
|
||||
tier_badge = f'<span class="tier-badge" style="background: {tier_color}">{tier_name}</span>'
|
||||
|
||||
days_remaining = user.get("tariff_days_remaining", 0)
|
||||
days_remaining = get_remaining_days(user)
|
||||
days_info = f"<p>⏳ Осталось дней: {days_remaining}</p>" if tier == "paid" and days_remaining > 0 else ""
|
||||
|
||||
traffic = get_cached_traffic(subscription_id)
|
||||
@@ -728,14 +742,15 @@ async def webhook_donationalerts(request: Request):
|
||||
|
||||
conn = get_db()
|
||||
try:
|
||||
now_ts = int(time.time())
|
||||
conn.execute("""
|
||||
UPDATE users SET
|
||||
tier = ?,
|
||||
tariff_days_bought = tariff_days_bought + ?,
|
||||
tariff_days_remaining = tariff_days_remaining + ?,
|
||||
tariff_end_at = MAX(COALESCE(tariff_end_at, 0), ?) + ? * 86400,
|
||||
total_paid_rubles = total_paid_rubles + ?
|
||||
WHERE id = ?
|
||||
""", (tier, days, days, amount, user["id"]))
|
||||
""", (tier, days, now_ts, days, amount, user["id"]))
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -764,18 +779,19 @@ async def admin_users(request: Request):
|
||||
traffic = f'{u["traffic_limit_gb"]} GB' if u['traffic_limit_gb'] > 0 else '∞'
|
||||
active = '✓' if u['is_active'] else '✗'
|
||||
tier_display = u['tier'].upper()
|
||||
rem_days = get_remaining_days(u)
|
||||
users_rows += f'''<tr>
|
||||
<td>{u['id']}</td>
|
||||
<td style="font-weight:600;color:var(--text)">{u['username']}</td>
|
||||
<td><code>{u['subscription_id']}</code></td>
|
||||
<td><span class="badge badge-{u['tier']}">{tier_display}</span></td>
|
||||
<td>{u['tariff_days_remaining']}</td>
|
||||
<td>{rem_days}</td>
|
||||
<td>{u['total_paid_rubles']}₽</td>
|
||||
<td>{traffic}</td>
|
||||
<td>{active}</td>
|
||||
<td>{u['created_at'][:10]}</td>
|
||||
<td>
|
||||
<button class="btn-sm" onclick="editUser({u['id']}, '{u['tier']}', {u['tariff_days_remaining']}, {u['traffic_limit_gb']}, {1 if u['is_active'] else 0})">✍️</button>
|
||||
<button class="btn-sm" onclick="editUser({u['id']}, '{u['tier']}', {rem_days}, {u['traffic_limit_gb']}, {1 if u['is_active'] else 0})">✍️</button>
|
||||
<button class="btn-sm danger" onclick="deleteUser({u['id']}, '{u['username']}')">🗑️</button>
|
||||
</td>
|
||||
</tr>'''
|
||||
@@ -1185,6 +1201,7 @@ async def update_user(request: Request, data: dict):
|
||||
user_id = int(data.get("id", 0))
|
||||
tier = str(data.get("tier", "free"))
|
||||
tariff_days_remaining = int(data.get("tariff_days_remaining", 0) or 0)
|
||||
tariff_end_at = int(time.time()) + tariff_days_remaining * 86400 if tariff_days_remaining > 0 else 0
|
||||
traffic_limit_gb = int(data.get("traffic_limit_gb", 0) or 0)
|
||||
is_active = 1 if data.get("is_active") in [True, "true", "on", "1", 1] else 0
|
||||
|
||||
@@ -1193,9 +1210,9 @@ async def update_user(request: Request, data: dict):
|
||||
conn = get_db()
|
||||
try:
|
||||
conn.execute("""
|
||||
UPDATE users SET tier = ?, tariff_days_remaining = ?, traffic_limit_gb = ?, is_active = ?
|
||||
UPDATE users SET tier = ?, tariff_days_remaining = ?, tariff_end_at = ?, traffic_limit_gb = ?, is_active = ?
|
||||
WHERE id = ?
|
||||
""", (tier, tariff_days_remaining, traffic_limit_gb, is_active, user_id))
|
||||
""", (tier, tariff_days_remaining, tariff_end_at, traffic_limit_gb, is_active, user_id))
|
||||
conn.commit()
|
||||
|
||||
updated = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone()
|
||||
@@ -1374,20 +1391,21 @@ async def poll_donationalerts():
|
||||
user = conn.execute("SELECT * FROM users WHERE username = ? COLLATE NOCASE", (username,)).fetchone()
|
||||
|
||||
if user:
|
||||
current_expiry = user.get("tariff_days_remaining", 0)
|
||||
if current_expiry > 0:
|
||||
new_expiry = current_expiry + days
|
||||
now_ts = int(time.time())
|
||||
current_end = user.get("tariff_end_at", 0)
|
||||
if current_end > now_ts:
|
||||
new_end = current_end + days * 86400
|
||||
else:
|
||||
new_expiry = days
|
||||
new_end = now_ts + days * 86400
|
||||
|
||||
conn.execute("""
|
||||
UPDATE users SET
|
||||
tier = ?,
|
||||
tariff_days_bought = tariff_days_bought + ?,
|
||||
tariff_days_remaining = ?,
|
||||
tariff_end_at = ?,
|
||||
total_paid_rubles = total_paid_rubles + ?
|
||||
WHERE id = ?
|
||||
""", (tier, days, new_expiry, amount, user["id"]))
|
||||
""", (tier, days, new_end, amount, user["id"]))
|
||||
conn.commit()
|
||||
|
||||
sub_id = user["subscription_id"]
|
||||
|
||||
Reference in New Issue
Block a user