AI-Voice-Agent-Node/public/websocket-test.html
2025-05-27 21:06:13 +05:30

324 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Test</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.container {
display: flex;
flex-direction: column;
gap: 20px;
}
.connection-status {
padding: 10px;
border-radius: 5px;
text-align: center;
font-weight: bold;
}
.connected {
background-color: #d4edda;
color: #155724;
}
.disconnected {
background-color: #f8d7da;
color: #721c24;
}
.connecting {
background-color: #fff3cd;
color: #856404;
}
.message-container {
border: 1px solid #ddd;
border-radius: 5px;
padding: 10px;
height: 300px;
overflow-y: auto;
}
.message {
margin-bottom: 10px;
padding: 8px;
border-radius: 5px;
}
.received {
background-color: #e9ecef;
}
.sent {
background-color: #d1ecf1;
text-align: right;
}
.controls {
display: flex;
gap: 10px;
}
input, button {
padding: 8px;
}
input {
flex-grow: 1;
}
button {
cursor: pointer;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
}
button:hover {
background-color: #0069d9;
}
button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
.token-input {
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>WebSocket Test Client</h1>
<div class="token-input">
<label for="token">JWT Token:</label>
<input type="text" id="token" placeholder="Enter your JWT token" style="width: 100%;">
</div>
<div id="status" class="connection-status disconnected">Disconnected</div>
<div class="controls">
<button id="connect">Connect</button>
<button id="disconnect" disabled>Disconnect</button>
</div>
<div class="message-container" id="messages"></div>
<div class="controls">
<input type="text" id="message" placeholder="Type a message..." disabled>
<button id="send" disabled>Send</button>
</div>
</div>
<script>
let socket = null;
let reconnectAttempts = 0;
const MAX_RECONNECT_ATTEMPTS = 5;
const RECONNECT_DELAY = 1000; // 1 second
let reconnectTimeout = null;
const statusElement = document.getElementById('status');
const messagesElement = document.getElementById('messages');
const messageInput = document.getElementById('message');
const tokenInput = document.getElementById('token');
const connectButton = document.getElementById('connect');
const disconnectButton = document.getElementById('disconnect');
const sendButton = document.getElementById('send');
function updateStatus(status, message) {
statusElement.className = 'connection-status ' + status;
statusElement.textContent = message;
console.log(`Status: ${status} - ${message}`);
}
function addMessage(message, type) {
const messageElement = document.createElement('div');
messageElement.className = 'message ' + type;
messageElement.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
messagesElement.appendChild(messageElement);
messagesElement.scrollTop = messagesElement.scrollHeight;
}
function setupWebSocket() {
const token = tokenInput.value.trim();
if (!token) {
alert('Please enter a JWT token');
return false;
}
// Use the current hostname and port for the WebSocket connection
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const host = window.location.hostname;
const port = window.location.port || (window.location.protocol === 'https:' ? '443' : '80');
const wsUrl = `${protocol}//${host}:${port}`;
updateStatus('connecting', 'Connecting...');
addMessage(`Connecting to ${wsUrl}...`, 'info');
try {
// Close existing connection if any
if (socket) {
socket.onclose = null; // Remove previous onclose handler
socket.close();
}
socket = new WebSocket(wsUrl);
socket.onopen = function() {
reconnectAttempts = 0; // Reset reconnect attempts on successful connection
updateStatus('connected', 'Connected');
addMessage('Connection established', 'received');
// Send authentication message with token
const authMessage = JSON.stringify({ token });
socket.send(authMessage);
connectButton.disabled = true;
disconnectButton.disabled = false;
messageInput.disabled = false;
sendButton.disabled = false;
// Focus the message input
messageInput.focus();
};
socket.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
let messageText = '';
if (data.type === 'CONNECTED') {
messageText = `Connected as user: ${data.message.split('as ')[1] || 'unknown'}`;
} else if (data.type === 'MESSAGE_RECEIVED') {
messageText = `Server: ${data.content}`;
} else if (data.type === 'ERROR') {
messageText = `Error: ${data.error}`;
} else if (data.type === 'ALERT') {
messageText = `Alert: ${JSON.stringify(data.payload)}`;
} else {
messageText = `Received: ${event.data}`;
}
addMessage(messageText, 'received');
} catch (e) {
console.error('Error processing message:', e);
addMessage(`Received invalid message: ${event.data}`, 'error');
}
};
socket.onclose = function(event) {
updateStatus('disconnected', 'Disconnected');
const reason = event.reason || 'Unknown reason';
const code = event.code || 'No code';
addMessage(`Connection closed. Code: ${code}, Reason: ${reason}`, 'received');
connectButton.disabled = false;
disconnectButton.disabled = true;
messageInput.disabled = true;
sendButton.disabled = true;
// Clear any existing reconnect timeout
if (reconnectTimeout) {
clearTimeout(reconnectTimeout);
}
// Attempt to reconnect if this wasn't a normal closure
if (event.code !== 1000 && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
reconnectAttempts++;
const delay = RECONNECT_DELAY * Math.pow(2, reconnectAttempts); // Exponential backoff
addMessage(`Attempting to reconnect (${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS}) in ${delay/1000} seconds...`, 'info');
reconnectTimeout = setTimeout(() => {
addMessage('Reconnecting...', 'info');
setupWebSocket();
}, delay);
} else if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
addMessage('Max reconnection attempts reached. Please check your connection and try again.', 'error');
}
socket = null;
};
socket.onerror = function(error) {
console.error('WebSocket error:', error);
updateStatus('error', 'Connection Error');
addMessage(`WebSocket error: ${error.message || 'Unknown error'}`, 'error');
};
return true;
} catch (error) {
console.error('WebSocket setup error:', error);
updateStatus('error', 'Connection Failed');
addMessage(`Failed to connect: ${error.message}`, 'error');
return false;
}
}
function connect() {
if (setupWebSocket()) {
// Disable connect button while connecting
connectButton.disabled = true;
}
}
function disconnect() {
// Clear any pending reconnect attempts
if (reconnectTimeout) {
clearTimeout(reconnectTimeout);
reconnectTimeout = null;
}
if (socket) {
// Use normal closure status code (1000) to indicate intentional disconnect
socket.close(1000, 'User disconnected');
}
}
function sendMessage() {
if (!socket || socket.readyState !== WebSocket.OPEN) {
addMessage('Not connected to server', 'error');
return;
}
const message = messageInput.value.trim();
if (!message) return;
try {
// Send a custom message
const messageObj = {
type: 'MESSAGE',
content: message,
timestamp: new Date().toISOString()
};
socket.send(JSON.stringify(messageObj));
addMessage(`You: ${message}`, 'sent');
messageInput.value = '';
} catch (error) {
console.error('Error sending message:', error);
addMessage(`Failed to send message: ${error.message}`, 'error');
}
}
// Event listeners
connectButton.addEventListener('click', connect);
disconnectButton.addEventListener('click', disconnect);
sendButton.addEventListener('click', sendMessage);
messageInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
sendMessage();
}
});
// Auto-connect if there's a token in the URL hash
document.addEventListener('DOMContentLoaded', function() {
const hash = window.location.hash.substring(1);
if (hash) {
tokenInput.value = hash;
// Small delay to ensure the UI is ready
setTimeout(connect, 500);
}
});
</script>
</body>
</html>