File size: 3,148 Bytes
fe83268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
607bc57
fe83268
 
607bc57
 
fe83268
 
 
 
607bc57
fe83268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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 };