|
|
<!DOCTYPE html>
|
|
|
<html lang="fa" dir="rtl">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>تست WebSocket - Crypto Monitor</title>
|
|
|
<link rel="stylesheet" href="/static/css/connection-status.css">
|
|
|
<style>
|
|
|
* {
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
body {
|
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
min-height: 100vh;
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
.container {
|
|
|
max-width: 1200px;
|
|
|
margin: 0 auto;
|
|
|
}
|
|
|
|
|
|
.card {
|
|
|
background: white;
|
|
|
border-radius: 20px;
|
|
|
padding: 30px;
|
|
|
margin-bottom: 20px;
|
|
|
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|
|
}
|
|
|
|
|
|
h1 {
|
|
|
color: #1f2937;
|
|
|
margin-bottom: 10px;
|
|
|
font-size: 32px;
|
|
|
}
|
|
|
|
|
|
h2 {
|
|
|
color: #4b5563;
|
|
|
margin-bottom: 20px;
|
|
|
font-size: 24px;
|
|
|
}
|
|
|
|
|
|
.status-grid {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
|
gap: 20px;
|
|
|
margin-bottom: 30px;
|
|
|
}
|
|
|
|
|
|
.status-card {
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
color: white;
|
|
|
padding: 20px;
|
|
|
border-radius: 15px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.status-value {
|
|
|
font-size: 48px;
|
|
|
font-weight: bold;
|
|
|
margin: 10px 0;
|
|
|
}
|
|
|
|
|
|
.status-label {
|
|
|
font-size: 14px;
|
|
|
opacity: 0.9;
|
|
|
}
|
|
|
|
|
|
.log-container {
|
|
|
background: #1e293b;
|
|
|
border-radius: 10px;
|
|
|
padding: 20px;
|
|
|
max-height: 400px;
|
|
|
overflow-y: auto;
|
|
|
font-family: 'Courier New', monospace;
|
|
|
font-size: 13px;
|
|
|
color: #e2e8f0;
|
|
|
}
|
|
|
|
|
|
.log-entry {
|
|
|
padding: 8px;
|
|
|
margin-bottom: 5px;
|
|
|
border-left: 3px solid #3b82f6;
|
|
|
background: rgba(59, 130, 246, 0.1);
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
.log-time {
|
|
|
color: #94a3b8;
|
|
|
margin-left: 10px;
|
|
|
}
|
|
|
|
|
|
.btn {
|
|
|
padding: 12px 24px;
|
|
|
border: none;
|
|
|
border-radius: 10px;
|
|
|
font-size: 16px;
|
|
|
font-weight: 600;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s;
|
|
|
margin: 5px;
|
|
|
}
|
|
|
|
|
|
.btn-primary {
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
color: white;
|
|
|
}
|
|
|
|
|
|
.btn-primary:hover {
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
|
|
|
}
|
|
|
|
|
|
.btn-success {
|
|
|
background: #10b981;
|
|
|
color: white;
|
|
|
}
|
|
|
|
|
|
.btn-danger {
|
|
|
background: #ef4444;
|
|
|
color: white;
|
|
|
}
|
|
|
|
|
|
.controls {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
flex-wrap: wrap;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.pulse {
|
|
|
animation: pulse 2s infinite;
|
|
|
}
|
|
|
|
|
|
@keyframes pulse {
|
|
|
0%, 100% {
|
|
|
opacity: 1;
|
|
|
transform: scale(1);
|
|
|
}
|
|
|
50% {
|
|
|
opacity: 0.7;
|
|
|
transform: scale(1.05);
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
|
|
|
<div id="ws-connection-status" class="ws-status-indicator disconnected">
|
|
|
<div id="ws-status-dot" class="status-dot status-dot-offline"></div>
|
|
|
<span id="ws-status-text" class="ws-status-text">در حال اتصال...</span>
|
|
|
<div id="online-users-badge" class="badge badge-info" style="margin-right: 10px;">0</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="container">
|
|
|
<div class="card">
|
|
|
<h1>🚀 تست WebSocket - Crypto Monitor</h1>
|
|
|
<p style="color: #6b7280; margin-bottom: 20px;">
|
|
|
این صفحه برای تست اتصال WebSocket و نمایش آمار بلادرنگ طراحی شده است.
|
|
|
</p>
|
|
|
|
|
|
<div class="status-grid">
|
|
|
<div class="status-card">
|
|
|
<div class="status-label">کاربران آنلاین</div>
|
|
|
<div class="status-value pulse" id="active-users-count">0</div>
|
|
|
</div>
|
|
|
<div class="status-card">
|
|
|
<div class="status-label">کل نشستها</div>
|
|
|
<div class="status-value" id="total-sessions-count">0</div>
|
|
|
</div>
|
|
|
<div class="status-card">
|
|
|
<div class="status-label">پیامهای دریافتی</div>
|
|
|
<div class="status-value" id="messages-received">0</div>
|
|
|
</div>
|
|
|
<div class="status-card">
|
|
|
<div class="status-label">پیامهای ارسالی</div>
|
|
|
<div class="status-value" id="messages-sent">0</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="controls">
|
|
|
<button class="btn btn-primary" onclick="requestStats()">📊 درخواست آمار</button>
|
|
|
<button class="btn btn-success" onclick="sendPing()">🏓 Ping</button>
|
|
|
<button class="btn btn-primary" onclick="subscribe('market')">📈 Subscribe Market</button>
|
|
|
<button class="btn btn-danger" onclick="clearLogs()">🗑️ پاک کردن لاگ</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<h2>📋 لاگ رویدادها</h2>
|
|
|
<div id="log-container" class="log-container">
|
|
|
<div class="log-entry">
|
|
|
<span class="log-time">[--:--:--]</span>
|
|
|
در انتظار اتصال WebSocket...
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<h2>📊 اطلاعات Session</h2>
|
|
|
<div id="session-info" style="font-family: monospace; background: #f3f4f6; padding: 15px; border-radius: 8px;">
|
|
|
<strong>Session ID:</strong> <span id="session-id">-</span><br>
|
|
|
<strong>وضعیت اتصال:</strong> <span id="connection-status">قطع شده</span><br>
|
|
|
<strong>تلاشهای اتصال:</strong> <span id="reconnect-attempts">0</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script src="/static/js/websocket-client.js"></script>
|
|
|
<script>
|
|
|
let messageCount = 0;
|
|
|
let sentCount = 0;
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
if (window.wsClient) {
|
|
|
setupWebSocketHandlers();
|
|
|
} else {
|
|
|
addLog('❌ خطا: WebSocket Client آماده نیست');
|
|
|
}
|
|
|
}, 1000);
|
|
|
|
|
|
function setupWebSocketHandlers() {
|
|
|
addLog('✅ WebSocket Client آماده شد');
|
|
|
|
|
|
|
|
|
window.wsClient.onConnection((connected) => {
|
|
|
document.getElementById('connection-status').textContent = connected ? 'متصل ✅' : 'قطع شده ❌';
|
|
|
document.getElementById('reconnect-attempts').textContent = window.wsClient.reconnectAttempts;
|
|
|
});
|
|
|
|
|
|
|
|
|
window.wsClient.on('welcome', (message) => {
|
|
|
addLog(`🎉 خوش آمدید! Session ID: ${message.session_id}`);
|
|
|
document.getElementById('session-id').textContent = message.session_id;
|
|
|
messageCount++;
|
|
|
updateMessageCount();
|
|
|
});
|
|
|
|
|
|
|
|
|
window.wsClient.on('stats_update', (message) => {
|
|
|
addLog('📊 آمار جدید دریافت شد');
|
|
|
const data = message.data;
|
|
|
|
|
|
if (data.active_connections !== undefined) {
|
|
|
document.getElementById('active-users-count').textContent = data.active_connections;
|
|
|
}
|
|
|
if (data.total_sessions !== undefined) {
|
|
|
document.getElementById('total-sessions-count').textContent = data.total_sessions;
|
|
|
}
|
|
|
|
|
|
messageCount++;
|
|
|
updateMessageCount();
|
|
|
});
|
|
|
|
|
|
|
|
|
window.wsClient.on('stats_response', (message) => {
|
|
|
addLog('📡 پاسخ آمار Provider دریافت شد');
|
|
|
console.log('Provider Stats:', message.data);
|
|
|
messageCount++;
|
|
|
updateMessageCount();
|
|
|
});
|
|
|
|
|
|
|
|
|
window.wsClient.on('pong', (message) => {
|
|
|
addLog('🏓 Pong دریافت شد');
|
|
|
messageCount++;
|
|
|
updateMessageCount();
|
|
|
});
|
|
|
|
|
|
|
|
|
window.wsClient.on('subscribed', (message) => {
|
|
|
addLog(`✅ Subscribe شد به: ${message.group}`);
|
|
|
messageCount++;
|
|
|
updateMessageCount();
|
|
|
});
|
|
|
|
|
|
|
|
|
window.wsClient.on('provider_stats', (message) => {
|
|
|
addLog('📡 آمار Provider بهروز شد');
|
|
|
messageCount++;
|
|
|
updateMessageCount();
|
|
|
});
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
requestStats();
|
|
|
}, 2000);
|
|
|
}
|
|
|
|
|
|
function requestStats() {
|
|
|
if (window.wsClient && window.wsClient.isConnected) {
|
|
|
window.wsClient.requestStats();
|
|
|
addLog('📤 درخواست آمار ارسال شد');
|
|
|
sentCount++;
|
|
|
updateSentCount();
|
|
|
} else {
|
|
|
addLog('⚠️ WebSocket متصل نیست');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function sendPing() {
|
|
|
if (window.wsClient && window.wsClient.isConnected) {
|
|
|
window.wsClient.send({ type: 'ping' });
|
|
|
addLog('📤 Ping ارسال شد');
|
|
|
sentCount++;
|
|
|
updateSentCount();
|
|
|
} else {
|
|
|
addLog('⚠️ WebSocket متصل نیست');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function subscribe(group) {
|
|
|
if (window.wsClient && window.wsClient.isConnected) {
|
|
|
window.wsClient.subscribe(group);
|
|
|
addLog(`📤 درخواست Subscribe به ${group} ارسال شد`);
|
|
|
sentCount++;
|
|
|
updateSentCount();
|
|
|
} else {
|
|
|
addLog('⚠️ WebSocket متصل نیست');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function addLog(message) {
|
|
|
const container = document.getElementById('log-container');
|
|
|
const time = new Date().toLocaleTimeString('fa-IR');
|
|
|
const entry = document.createElement('div');
|
|
|
entry.className = 'log-entry';
|
|
|
entry.innerHTML = `<span class="log-time">[${time}]</span> ${message}`;
|
|
|
container.insertBefore(entry, container.firstChild);
|
|
|
|
|
|
|
|
|
while (container.children.length > 50) {
|
|
|
container.removeChild(container.lastChild);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function clearLogs() {
|
|
|
document.getElementById('log-container').innerHTML = '';
|
|
|
addLog('🗑️ لاگها پاک شدند');
|
|
|
}
|
|
|
|
|
|
function updateMessageCount() {
|
|
|
document.getElementById('messages-received').textContent = messageCount;
|
|
|
}
|
|
|
|
|
|
function updateSentCount() {
|
|
|
document.getElementById('messages-sent').textContent = sentCount;
|
|
|
}
|
|
|
|
|
|
|
|
|
setInterval(() => {
|
|
|
if (window.wsClient && window.wsClient.isConnected) {
|
|
|
requestStats();
|
|
|
}
|
|
|
}, 10000);
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|
|
|
|
|
|
|