fix: dynamic days remaining via tariff_end_at timestamp; auto-downgrade when expired

This commit is contained in:
SashegDev
2026-05-23 14:27:43 +00:00
parent dc6d1212d6
commit 09f1b7b261
+34 -16
View File
@@ -81,6 +81,12 @@ def clear_cache(sub_id: str = None):
_links_cache.clear() _links_cache.clear()
_traffic_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: def load_json(path: str, default: dict) -> dict:
if os.path.exists(path): if os.path.exists(path):
try: try:
@@ -107,12 +113,19 @@ def init_db():
tier TEXT DEFAULT 'free', tier TEXT DEFAULT 'free',
tariff_days_bought INTEGER DEFAULT 0, tariff_days_bought INTEGER DEFAULT 0,
tariff_days_remaining INTEGER DEFAULT 0, tariff_days_remaining INTEGER DEFAULT 0,
tariff_end_at INTEGER DEFAULT 0,
total_paid_rubles INTEGER DEFAULT 0, total_paid_rubles INTEGER DEFAULT 0,
traffic_limit_gb INTEGER DEFAULT 0, traffic_limit_gb INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT 1, is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 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.commit()
conn.close() conn.close()
@@ -376,7 +389,7 @@ VALUES (?, ?, 'free', 0, 0, 0, 0, 1)
user = dict(user) 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.execute("UPDATE users SET tier = 'free' WHERE id = ?", (user['id'],))
conn.commit() conn.commit()
user['tier'] = 'free' 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}") lines.append(f"#support-url: {support_url}")
expire_ts = 0 expire_ts = 0
if user.get("tariff_days_remaining", 0) > 0: rem_days = get_remaining_days(user)
expire_ts = int((datetime.now() + timedelta(days=user["tariff_days_remaining"])).timestamp()) if rem_days > 0:
expire_ts = int((datetime.now() + timedelta(days=rem_days)).timestamp())
lines.append("#sub-expire: 1") lines.append("#sub-expire: 1")
if support_url: if support_url:
lines.append(f"#sub-expire-button-link: {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_name = tier_config.get("name", "Free")
tier_badge = f'<span class="tier-badge" style="background: {tier_color}">{tier_name}</span>' 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 "" days_info = f"<p>⏳ Осталось дней: {days_remaining}</p>" if tier == "paid" and days_remaining > 0 else ""
traffic = get_cached_traffic(subscription_id) traffic = get_cached_traffic(subscription_id)
@@ -728,14 +742,15 @@ async def webhook_donationalerts(request: Request):
conn = get_db() conn = get_db()
try: try:
now_ts = int(time.time())
conn.execute(""" conn.execute("""
UPDATE users SET UPDATE users SET
tier = ?, tier = ?,
tariff_days_bought = tariff_days_bought + ?, 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 + ? total_paid_rubles = total_paid_rubles + ?
WHERE id = ? WHERE id = ?
""", (tier, days, days, amount, user["id"])) """, (tier, days, now_ts, days, amount, user["id"]))
conn.commit() conn.commit()
finally: finally:
conn.close() 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 '&#8734;' traffic = f'{u["traffic_limit_gb"]} GB' if u['traffic_limit_gb'] > 0 else '&#8734;'
active = '&#10003;' if u['is_active'] else '&#10007;' active = '&#10003;' if u['is_active'] else '&#10007;'
tier_display = u['tier'].upper() tier_display = u['tier'].upper()
rem_days = get_remaining_days(u)
users_rows += f'''<tr> users_rows += f'''<tr>
<td>{u['id']}</td> <td>{u['id']}</td>
<td style="font-weight:600;color:var(--text)">{u['username']}</td> <td style="font-weight:600;color:var(--text)">{u['username']}</td>
<td><code>{u['subscription_id']}</code></td> <td><code>{u['subscription_id']}</code></td>
<td><span class="badge badge-{u['tier']}">{tier_display}</span></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']}&#8381;</td> <td>{u['total_paid_rubles']}&#8381;</td>
<td>{traffic}</td> <td>{traffic}</td>
<td>{active}</td> <td>{active}</td>
<td>{u['created_at'][:10]}</td> <td>{u['created_at'][:10]}</td>
<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})">&#9997;&#65039;</button> <button class="btn-sm" onclick="editUser({u['id']}, '{u['tier']}', {rem_days}, {u['traffic_limit_gb']}, {1 if u['is_active'] else 0})">&#9997;&#65039;</button>
<button class="btn-sm danger" onclick="deleteUser({u['id']}, '{u['username']}')">&#128465;&#65039;</button> <button class="btn-sm danger" onclick="deleteUser({u['id']}, '{u['username']}')">&#128465;&#65039;</button>
</td> </td>
</tr>''' </tr>'''
@@ -1185,6 +1201,7 @@ async def update_user(request: Request, data: dict):
user_id = int(data.get("id", 0)) user_id = int(data.get("id", 0))
tier = str(data.get("tier", "free")) tier = str(data.get("tier", "free"))
tariff_days_remaining = int(data.get("tariff_days_remaining", 0) or 0) 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) 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 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() conn = get_db()
try: try:
conn.execute(""" 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 = ? 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() conn.commit()
updated = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone() 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() user = conn.execute("SELECT * FROM users WHERE username = ? COLLATE NOCASE", (username,)).fetchone()
if user: if user:
current_expiry = user.get("tariff_days_remaining", 0) now_ts = int(time.time())
if current_expiry > 0: current_end = user.get("tariff_end_at", 0)
new_expiry = current_expiry + days if current_end > now_ts:
new_end = current_end + days * 86400
else: else:
new_expiry = days new_end = now_ts + days * 86400
conn.execute(""" conn.execute("""
UPDATE users SET UPDATE users SET
tier = ?, tier = ?,
tariff_days_bought = tariff_days_bought + ?, tariff_days_bought = tariff_days_bought + ?,
tariff_days_remaining = ?, tariff_end_at = ?,
total_paid_rubles = total_paid_rubles + ? total_paid_rubles = total_paid_rubles + ?
WHERE id = ? WHERE id = ?
""", (tier, days, new_expiry, amount, user["id"])) """, (tier, days, new_end, amount, user["id"]))
conn.commit() conn.commit()
sub_id = user["subscription_id"] sub_id = user["subscription_id"]