const { send, broadcast } = require("./utils"); const { createRoom, joinRoom, removeFromRoom, getRoom, getParticipantList } = require("./room"); function handleMessage(ws, raw) { let msg; try { msg = JSON.parse(raw); } catch { return send(ws, { type: "error", message: "Invalid JSON" }); } console.log("[server] recv:", msg.type, JSON.stringify(msg)); switch (msg.type) { case "create-room": { if (msg.url) ws._url = msg.url; const roomCode = createRoom(ws); console.log("[server] room created:", roomCode); const room = getRoom(roomCode); send(ws, { type: "room-created", roomCode, count: 1, members: getParticipantList(room) }); break; } case "join-room": { if (msg.url) ws._url = msg.url; const room = joinRoom(ws, msg.roomCode); if (!room) { console.log("[server] room not found:", msg.roomCode); return send(ws, { type: "error", message: "Room not found" }); } console.log("[server] joined room:", msg.roomCode, "participants:", room.participants.size); send(ws, { type: "room-joined", roomCode: msg.roomCode, count: room.participants.size, members: getParticipantList(room) }); broadcast(room, { type: "participant-update", count: room.participants.size, members: getParticipantList(room) }, ws); break; } case "video-event": { const room = getRoom(ws._roomCode); if (!room) return send(ws, { type: "error", message: "Not in a room" }); console.log("[server] video-event:", msg.event, "from room", ws._roomCode, "broadcasting to", room.participants.size - 1, "others"); broadcast(room, { type: "video-event", event: msg.event, timestamp: msg.timestamp, }, ws); break; } case "sync-request": { const room = getRoom(ws._roomCode); if (!room) return send(ws, { type: "error", message: "Not in a room" }); // Forward the request to the host; tag it so the host knows who to reply to ws._syncId = true; send(room.host, { type: "sync-request" }); break; } case "sync-response": { const room = getRoom(ws._roomCode); if (!room) return send(ws, { type: "error", message: "Not in a room" }); // Send to the participant who requested the sync for (const p of room.participants) { if (p._syncId && p !== ws) { send(p, { type: "sync-response", playing: msg.playing, timestamp: msg.timestamp }); p._syncId = false; } } break; } case "update-url": { const room = getRoom(ws._roomCode); if (!room) return send(ws, { type: "error", message: "Not in a room" }); ws._url = msg.url; console.log("[server] update-url:", msg.url, "in room", ws._roomCode); broadcast(room, { type: "participant-update", count: room.participants.size, members: getParticipantList(room) }); break; } default: send(ws, { type: "error", message: `Unknown message type: ${msg.type}` }); } } function handleClose(ws) { removeFromRoom(ws); } module.exports = { handleMessage, handleClose };