video-sync-backend / handlers.js
rtrm's picture
rtrm HF Staff
feat: include URL in create/join room messages
607bc57 unverified
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 };