MT / webui.py
Nailioq's picture
Upload 7 files
b460680 verified
Raw
History Blame Contribute Delete
4.9 kB
from flask import Flask, jsonify, render_template_string
import psutil
import mtprotoproxy
import time
import os
app = Flask(__name__)
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MTProto Proxy Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; padding-top: 20px; }
.card { margin-bottom: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
.metric-value { font-size: 2rem; font-weight: bold; color: #0d6efd; }
</style>
<script>
async function updateStats() {
try {
const response = await fetch('/api/stats');
const data = await response.json();
document.getElementById('cpu-load').innerText = data.cpu_percent + '%';
document.getElementById('mem-load').innerText = data.mem_percent + '%';
// Calculate total connections
let totalConnections = 0;
let userHtml = '';
for (const [user, stats] of Object.entries(data.user_stats)) {
totalConnections += stats.curr_connects || 0;
userHtml += `<tr>
<td>${user}</td>
<td>${stats.curr_connects || 0}</td>
<td>${stats.connects || 0}</td>
<td>${(((stats.octets_from_client || 0) + (stats.octets_to_client || 0)) / 1024 / 1024).toFixed(2)} MB</td>
</tr>`;
}
document.getElementById('total-users').innerText = totalConnections;
document.getElementById('user-table-body').innerHTML = userHtml;
} catch (e) {
console.error("Failed to fetch stats", e);
}
}
setInterval(updateStats, 2000);
window.onload = updateStats;
</script>
</head>
<body>
<div class="container">
<h1 class="mb-4 text-center">MTProto Proxy Dashboard</h1>
<div class="row">
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">Active Connections</h5>
<p class="metric-value" id="total-users">0</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">CPU Load</h5>
<p class="metric-value" id="cpu-load">0%</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">Memory Load</h5>
<p class="metric-value" id="mem-load">0%</p>
</div>
</div>
</div>
</div>
<div class="card mt-4">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">User Statistics</h5>
</div>
<div class="card-body">
<table class="table table-striped">
<thead>
<tr>
<th>User Name</th>
<th>Active Connections</th>
<th>Total Connects</th>
<th>Data Transferred</th>
</tr>
</thead>
<tbody id="user-table-body">
<!-- Filled by JS -->
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
"""
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
@app.route('/api/stats')
def stats():
user_stats = {}
try:
# mtprotoproxy.user_stats is a defaultdict of Counter
# Need to copy list of items first since dictionary can change size during iteration
items = list(mtprotoproxy.user_stats.items())
for user, counter in items:
user_stats[user] = dict(counter)
except Exception as e:
print(f"Error reading stats: {e}")
return jsonify({
"cpu_percent": psutil.cpu_percent(interval=None),
"mem_percent": psutil.virtual_memory().percent,
"user_stats": user_stats
})
def start_webui():
# Make sure we don't start the reloader, as we're running alongside asyncio loop
app.run(host='0.0.0.0', port=7860, debug=False, use_reloader=False)
if __name__ == "__main__":
start_webui()