diff --git a/desktop/src/api/rooms/rooms.websocket.ts b/desktop/src/api/rooms/rooms.websocket.ts index 2b1a699..de85db2 100644 --- a/desktop/src/api/rooms/rooms.websocket.ts +++ b/desktop/src/api/rooms/rooms.websocket.ts @@ -42,8 +42,7 @@ async function handleWebSocketConnection(connection: any, req: any) { const token = req.query.token; const guestName = req.query.guestName; const password = req.query.password; - - const clientIP = getClientIP(req); // NUEVO + const clientIP = getClientIP(req); let userId: string; let username: string; @@ -52,46 +51,21 @@ async function handleWebSocketConnection(connection: any, req: any) { let realUserId: any; const room = roomService.getRoom(roomId); + + // 1. Validaciones básicas de existencia y Ban if (!room) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Room not found' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Room not found' })); socket.close(); return; } if (roomService.isIPBanned(roomId, clientIP)) { - socket.send(JSON.stringify({ - type: 'error', - message: 'You have been banned from this room' - })); + socket.send(JSON.stringify({ type: 'error', message: 'You have been banned from this room' })); socket.close(); return; } - if (!room) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Room not found' - })); - socket.close(); - return; - } - - // Verificar contraseña si existe - if (room.password) { - if (!password || !roomService.verifyRoomPassword(roomId, password)) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Invalid password' - })); - socket.close(); - return; - } - } - - // Autenticar usuario o crear invitado + // 2. MOVIDO ARRIBA: Autenticar usuario PRIMERO para saber quién es if (token) { try { const decoded: any = jwt.verify(token, process.env.JWT_SECRET!); @@ -107,50 +81,41 @@ async function handleWebSocketConnection(connection: any, req: any) { throw new Error('User not found'); } } catch (err) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Invalid token' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Invalid token' })); socket.close(); return; } } else if (guestName && guestName.trim()) { + // ... (Lógica de Guest se mantiene igual) ... const nameToCheck = guestName.trim(); - const isNameTaken = Array.from(room.users.values()).some( u => u.username.toLowerCase() === nameToCheck.toLowerCase() ); - if (isNameTaken) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Username is already taken' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Username is already taken' })); socket.close(); return; } - userId = `guest_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; username = nameToCheck; isGuest = true; } else { - socket.send(JSON.stringify({ - type: 'error', - message: 'Authentication required' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Authentication required' })); socket.close(); return; } + // 3. Determinar si es Host const isHost = room.host.userId === realUserId || room.host.id === userId; - console.log('WebSocket Connection:', { - userId, - realUserId, - roomHostId: room.host.id, - roomHostUserId: room.host.userId, - isHost - }); + // 4. MOVIDO ABAJO: Validar contraseña SOLO SI NO ES HOST + if (room.password && !isHost) { + if (!password || !roomService.verifyRoomPassword(roomId, password)) { + socket.send(JSON.stringify({ type: 'error', message: 'Invalid password' })); + socket.close(); + return; + } + } const userInRoom = { id: userId, diff --git a/desktop/src/scripts/room.js b/desktop/src/scripts/room.js index 94aae86..f266ce1 100644 --- a/desktop/src/scripts/room.js +++ b/desktop/src/scripts/room.js @@ -15,6 +15,7 @@ const RoomsApp = (function() { let modalTotalEpisodes = 0; const MODAL_EPS_PER_PAGE = 50; let currentQueue = []; + let shouldReconnect = true; let configState = { extension: null, @@ -160,6 +161,7 @@ const RoomsApp = (function() { function handleInitialEntry(roomInfo) { const token = localStorage.getItem('token'); const passwordGroup = document.getElementById('password-group'); + const guestNameInput = document.getElementById('guest-name-input'); const hostInfoDiv = document.getElementById('join-host-info'); const hostAvatar = document.getElementById('join-host-avatar'); @@ -176,24 +178,31 @@ const RoomsApp = (function() { passwordGroup.dataset.required = roomInfo.hasPassword ? 'true' : 'false'; } + if (token && guestNameInput) { + const parentGroup = guestNameInput.closest('.form-group') || guestNameInput; + parentGroup.style.display = 'none'; + } else if (guestNameInput) { + const parentGroup = guestNameInput.closest('.form-group') || guestNameInput; + parentGroup.style.display = 'block'; + } + window.__roomPublicUrl = roomInfo.publicUrl || null; window.__roomExposed = roomInfo.exposed || false; - - console.log('Room info loaded:', { - exposed: window.__roomExposed, - publicUrl: window.__roomPublicUrl - }); - if (token) { connectToRoom(currentRoomId); } else { - console.log('Guest user, showing modal...'); if (elements.joinRoomModal) { elements.joinRoomModal.classList.add('show'); - const nameInput = document.getElementById('guest-name-input'); - if (nameInput) { - nameInput.value = ''; - setTimeout(() => nameInput.focus(), 100); + + if (roomInfo.hasPassword) { + setTimeout(() => { + const passInput = document.getElementById('join-password-input'); + if(passInput) passInput.focus(); + }, 100); + } else { + setTimeout(() => { + if(guestNameInput) guestNameInput.focus(); + }, 100); } } } @@ -983,6 +992,7 @@ const RoomsApp = (function() { closeModal(); }); function connectToRoom(roomId, guestName, password) { + shouldReconnect = true; const token = localStorage.getItem('token'); const isTunnel = window.location.hostname.includes('trycloudflare.com'); @@ -1034,7 +1044,7 @@ const RoomsApp = (function() { ws.onclose = (event) => { console.log('WebSocket Disconnected:', event.code, event.reason); - + if (!shouldReconnect) return; if (window.AnimePlayer && typeof window.AnimePlayer.setWebSocket === 'function') { window.AnimePlayer.setWebSocket(null); } @@ -1115,6 +1125,7 @@ const RoomsApp = (function() { function handleWebSocketMessage(data) { switch (data.type) { case 'error': + shouldReconnect = false; handleConnectionError(data.message); break; diff --git a/docker/src/api/rooms/rooms.websocket.ts b/docker/src/api/rooms/rooms.websocket.ts index 2b1a699..de85db2 100644 --- a/docker/src/api/rooms/rooms.websocket.ts +++ b/docker/src/api/rooms/rooms.websocket.ts @@ -42,8 +42,7 @@ async function handleWebSocketConnection(connection: any, req: any) { const token = req.query.token; const guestName = req.query.guestName; const password = req.query.password; - - const clientIP = getClientIP(req); // NUEVO + const clientIP = getClientIP(req); let userId: string; let username: string; @@ -52,46 +51,21 @@ async function handleWebSocketConnection(connection: any, req: any) { let realUserId: any; const room = roomService.getRoom(roomId); + + // 1. Validaciones básicas de existencia y Ban if (!room) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Room not found' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Room not found' })); socket.close(); return; } if (roomService.isIPBanned(roomId, clientIP)) { - socket.send(JSON.stringify({ - type: 'error', - message: 'You have been banned from this room' - })); + socket.send(JSON.stringify({ type: 'error', message: 'You have been banned from this room' })); socket.close(); return; } - if (!room) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Room not found' - })); - socket.close(); - return; - } - - // Verificar contraseña si existe - if (room.password) { - if (!password || !roomService.verifyRoomPassword(roomId, password)) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Invalid password' - })); - socket.close(); - return; - } - } - - // Autenticar usuario o crear invitado + // 2. MOVIDO ARRIBA: Autenticar usuario PRIMERO para saber quién es if (token) { try { const decoded: any = jwt.verify(token, process.env.JWT_SECRET!); @@ -107,50 +81,41 @@ async function handleWebSocketConnection(connection: any, req: any) { throw new Error('User not found'); } } catch (err) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Invalid token' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Invalid token' })); socket.close(); return; } } else if (guestName && guestName.trim()) { + // ... (Lógica de Guest se mantiene igual) ... const nameToCheck = guestName.trim(); - const isNameTaken = Array.from(room.users.values()).some( u => u.username.toLowerCase() === nameToCheck.toLowerCase() ); - if (isNameTaken) { - socket.send(JSON.stringify({ - type: 'error', - message: 'Username is already taken' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Username is already taken' })); socket.close(); return; } - userId = `guest_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; username = nameToCheck; isGuest = true; } else { - socket.send(JSON.stringify({ - type: 'error', - message: 'Authentication required' - })); + socket.send(JSON.stringify({ type: 'error', message: 'Authentication required' })); socket.close(); return; } + // 3. Determinar si es Host const isHost = room.host.userId === realUserId || room.host.id === userId; - console.log('WebSocket Connection:', { - userId, - realUserId, - roomHostId: room.host.id, - roomHostUserId: room.host.userId, - isHost - }); + // 4. MOVIDO ABAJO: Validar contraseña SOLO SI NO ES HOST + if (room.password && !isHost) { + if (!password || !roomService.verifyRoomPassword(roomId, password)) { + socket.send(JSON.stringify({ type: 'error', message: 'Invalid password' })); + socket.close(); + return; + } + } const userInRoom = { id: userId, diff --git a/docker/src/scripts/room.js b/docker/src/scripts/room.js index ad5698f..9e23343 100644 --- a/docker/src/scripts/room.js +++ b/docker/src/scripts/room.js @@ -15,6 +15,7 @@ const RoomsApp = (function() { let modalTotalEpisodes = 0; const MODAL_EPS_PER_PAGE = 50; let currentQueue = []; + let shouldReconnect = true; let configState = { extension: null, @@ -160,6 +161,7 @@ const RoomsApp = (function() { function handleInitialEntry(roomInfo) { const token = localStorage.getItem('token'); const passwordGroup = document.getElementById('password-group'); + const guestNameInput = document.getElementById('guest-name-input'); const hostInfoDiv = document.getElementById('join-host-info'); const hostAvatar = document.getElementById('join-host-avatar'); @@ -176,24 +178,31 @@ const RoomsApp = (function() { passwordGroup.dataset.required = roomInfo.hasPassword ? 'true' : 'false'; } + if (token && guestNameInput) { + const parentGroup = guestNameInput.closest('.form-group') || guestNameInput; + parentGroup.style.display = 'none'; + } else if (guestNameInput) { + const parentGroup = guestNameInput.closest('.form-group') || guestNameInput; + parentGroup.style.display = 'block'; + } + window.__roomPublicUrl = roomInfo.publicUrl || null; window.__roomExposed = roomInfo.exposed || false; - - console.log('Room info loaded:', { - exposed: window.__roomExposed, - publicUrl: window.__roomPublicUrl - }); - if (token) { connectToRoom(currentRoomId); } else { - console.log('Guest user, showing modal...'); if (elements.joinRoomModal) { elements.joinRoomModal.classList.add('show'); - const nameInput = document.getElementById('guest-name-input'); - if (nameInput) { - nameInput.value = ''; - setTimeout(() => nameInput.focus(), 100); + + if (roomInfo.hasPassword) { + setTimeout(() => { + const passInput = document.getElementById('join-password-input'); + if(passInput) passInput.focus(); + }, 100); + } else { + setTimeout(() => { + if(guestNameInput) guestNameInput.focus(); + }, 100); } } } @@ -983,6 +992,7 @@ const RoomsApp = (function() { closeModal(); }); function connectToRoom(roomId, guestName, password) { + shouldReconnect = true; const token = localStorage.getItem('token'); const isTunnel = window.location.hostname.includes('trycloudflare.com'); @@ -1034,7 +1044,7 @@ const RoomsApp = (function() { ws.onclose = (event) => { console.log('WebSocket Disconnected:', event.code, event.reason); - + if (!shouldReconnect) return; if (window.AnimePlayer && typeof window.AnimePlayer.setWebSocket === 'function') { window.AnimePlayer.setWebSocket(null); } @@ -1115,6 +1125,7 @@ const RoomsApp = (function() { function handleWebSocketMessage(data) { switch (data.type) { case 'error': + shouldReconnect = false; handleConnectionError(data.message); break;