Spaces:
Sleeping
Sleeping
| 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 }; | |