- XSS: render from_number/code via textContent, drop innerHTML string concat - Poll throttle: last_check column + 3s min between SMSPool /sms/check calls - provider_cost: store REAL + CAST in admin SUM (was silently summing text as 0) - Atomic debit: _debit() with balance_sats >= ? guard, debit-before-provision, refund ledger entry on provision failure (no double-spend window) - _extract_sms: defensive field parsing (text/body/message/content, number/sender/from) - admin: add PROVIDER COST card (USD)
49 lines
3.8 KiB
HTML
49 lines
3.8 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}SMS Admin — Clean Proxys{% endblock %}
|
|
{% block body %}
|
|
<div style="max-width:900px;margin:0 auto;padding:24px 0">
|
|
<h1 style="font-size:1.9rem;letter-spacing:-.5px">SMS <b style="color:#0ff">Admin</b></h1>
|
|
<p style="color:#94a3b8;margin:6px 0 16px">SMSPool balance: <b style="color:#0ff">{{ smspool_balance if smspool_balance is not none else 'unavailable' }} USD</b> · <span style="color:#f59e0b">Rental ceiling: 20 min (SMSPool hard cap — longer sessions need a re-rent loop)</span></p>
|
|
|
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-bottom:20px">
|
|
<div style="background:rgba(20,28,40,.6);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:14px"><div style="font-size:.7rem;color:#94a3b8;letter-spacing:.1em">ACTIVE</div><div style="font-size:1.6rem;color:#fff">{{ stats.active }}</div></div>
|
|
<div style="background:rgba(20,28,40,.6);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:14px"><div style="font-size:.7rem;color:#94a3b8;letter-spacing:.1em">SESSIONS</div><div style="font-size:1.6rem;color:#fff">{{ stats.total_sessions }}</div></div>
|
|
<div style="background:rgba(20,28,40,.6);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:14px"><div style="font-size:.7rem;color:#94a3b8;letter-spacing:.1em">SMS RECEIVED</div><div style="font-size:1.6rem;color:#fff">{{ stats.sms_received }}</div></div>
|
|
<div style="background:rgba(20,28,40,.6);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:14px"><div style="font-size:.7rem;color:#94a3b8;letter-spacing:.1em">REVENUE</div><div style="font-size:1.6rem;color:#4ade80">{{ stats.revenue_sats }} sats</div></div>
|
|
<div style="background:rgba(20,28,40,.6);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:14px"><div style="font-size:.7rem;color:#94a3b8;letter-spacing:.1em">PROVIDER COST</div><div style="font-size:1.6rem;color:#f59e0b">${{ '%.2f'|format(stats.provider_cost_usd) }}</div></div>
|
|
</div>
|
|
|
|
<h2 style="font-size:1.2rem;margin:20px 0 10px">Pricing (sats)</h2>
|
|
<form method="POST" action="/admin/sms" style="display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;margin-bottom:24px">
|
|
{% for p in pricing %}
|
|
<div>
|
|
<label style="display:block;font-size:.72rem;color:#94a3b8">{{ p.duration_min }} min</label>
|
|
<input name="price_{{ p.duration_min }}" value="{{ p.price_sats }}" style="width:90px;background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.15);color:#fff;padding:8px;border-radius:8px;font-family:monospace">
|
|
</div>
|
|
{% endfor %}
|
|
<button type="submit" style="background:linear-gradient(135deg,#0ff,#0af);color:#00141a;border:none;padding:9px 16px;border-radius:8px;font-weight:700;cursor:pointer">Save prices</button>
|
|
</form>
|
|
|
|
<h2 style="font-size:1.2rem;margin:16px 0 10px">Recent sessions</h2>
|
|
<table style="width:100%;border-collapse:collapse;font-size:.82rem">
|
|
<thead><tr style="text-align:left;color:#94a3b8">
|
|
<th style="padding:6px">ID</th><th>User</th><th>Number</th><th>Service</th><th>Status</th><th>Price</th><th>Cost</th><th>Created</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
{% for s in sessions %}
|
|
<tr style="border-top:1px solid rgba(255,255,255,.06)">
|
|
<td style="padding:6px">{{ s.id }}</td>
|
|
<td>{{ s.username }}</td>
|
|
<td style="font-family:monospace">{{ s.number }}</td>
|
|
<td>{{ s.service_name }}</td>
|
|
<td><span style="color:{{ '#4ade80' if s.status == 'sms_received' else '#0ff' if s.status == 'active' else '#94a3b8' }}">{{ s.status }}</span></td>
|
|
<td>{{ s.price_sats }}</td>
|
|
<td>${{ s.provider_cost }}</td>
|
|
<td style="color:#94a3b8">{{ s.created_at }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endblock %}
|