File size: 4,279 Bytes
d3bdf51
 
42e18e6
d3bdf51
7fe989f
d3bdf51
 
7fe989f
d3bdf51
 
 
 
 
 
7fe989f
 
 
d441744
 
 
 
 
 
7fe989f
d441744
904caf7
7fe989f
 
 
d441744
7fe989f
 
 
904caf7
 
d441744
904caf7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7fe989f
904caf7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7fe989f
904caf7
 
 
 
7fe989f
904caf7
 
 
 
 
7fe989f
904caf7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7fe989f
d3bdf51
 
 
 
7fe989f
d3bdf51
 
 
 
 
7fe989f
d3bdf51
 
 
 
 
 
6d4d78a
7fe989f
d3bdf51
 
 
 
7fe989f
d3bdf51
 
 
 
 
7fe989f
 
d3bdf51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7fe989f
6d4d78a
d3bdf51
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// server.js (for Bun)
import { serve } from "bun";

const rooms = new Map(); // roomId → Set<WebSocket>

serve({
  port: Number(process.env.PORT) || 7860,

  // Serve the HTML page at “/”
  async fetch(req) {
    const url = new URL(req.url);
    if (url.pathname !== "/") return new Response("Not Found", { status: 404 });

    return new Response(`<!doctype html>
<html>
<head>
  <title>Dubem Realtime Rooms</title>
  <meta charset="utf-8" />
  <style>
    body { font-family: sans-serif; padding: 20px; background: #f0f0f0; }
    #log { border: 1px solid #ccc; height: 200px; overflow-y: auto; padding: 10px; background: #fff; }
    input, button { margin: 5px 0; padding: 8px; font-size: 16px; }
  </style>
</head>
<body>
  <h2>Join a Room & Send Messages (truly 1)</h2>
  <input id="room" placeholder="Room ID" />
  <button onclick="joinRoom()">Join Room</button>
  <div id="log"></div>
  <input id="msg" placeholder="Type a message" style="width:80%;" />
  <button onclick="sendMsg()">Send</button>

  <script>
  let ws;
  let currentRoom = null;

  window.addEventListener('load', () => {
    // scheme + host from location, no interpolation syntax
    var scheme = location.protocol === 'https:' ? 'wss' : 'ws';
    var socketUrl = scheme + '://' + location.host + '/';
    console.log('Connecting to ' + socketUrl);

    ws = new WebSocket(socketUrl);

    ws.onopen = function() {
      log('🔌 Connected to server');
    };

    ws.onmessage = function(event) {
      var msg = JSON.parse(event.data);
      log('🗨️ [' + msg.roomId + '] ' + msg.message);
    };

    ws.onerror = function(event) {
      console.error('WebSocket error event:', event);
      log('⚠️ WebSocket error. Check console.');
    };

    ws.onclose = function(event) {
      log('❌ Disconnected (code=' + event.code + ' reason="' +
          (event.reason || 'none') + '")');
    };
  });

  function joinRoom() {
    var roomId = document.getElementById('room').value.trim();
    if (!roomId) return alert('Please enter a room ID');
    if (!ws || ws.readyState !== ws.OPEN) {
      return alert('Socket not open yet!');
    }
    ws.send(JSON.stringify({ action: 'join', roomId: roomId }));
    currentRoom = roomId;
    log('➡️ Joined room: ' + roomId);
  }

  function sendMsg() {
    var txt = document.getElementById('msg').value.trim();
    if (!txt) return;
    if (!ws || ws.readyState !== ws.OPEN) {
      return alert('Socket not open yet!');
    }
    if (!currentRoom) {
      return alert('Please join a room first');
    }
    ws.send(JSON.stringify({
      action: 'post',
      roomId: currentRoom,
      message: txt
    }));
    document.getElementById('msg').value = '';
  }

  function log(text) {
    var el = document.getElementById('log');
    el.innerHTML += '<div>' + text + '</div>';
    el.scrollTop = el.scrollHeight;
  }
</script>
</body>
</html>`, {
      headers: { "Content-Type": "text/html; charset=utf-8" },
    });
  },

  // Hook into Bun's WebSocket handling
  websocket: {
    open(ws) {
      // no-op here; clients join via “join” action
    },

    message(ws, raw) {
      let msg;
      try {
        msg = JSON.parse(raw.toString());
      } catch {
        return;
      }

      if (msg.action === "join" && msg.roomId) {
        // remove from all rooms
        for (const clients of rooms.values()) {
          clients.delete(ws);
        }
        // add to new room
        const roomSet = rooms.get(msg.roomId) || new Set();
        roomSet.add(ws);
        rooms.set(msg.roomId, roomSet);
        return;
      }

      if (msg.action === "post" && msg.roomId && msg.message) {
        const clients = rooms.get(msg.roomId);
        if (!clients) return;
        const payload = JSON.stringify({
          roomId: msg.roomId,
          message: msg.message,
          timestamp: Date.now(),
        });
        for (const client of clients) {
          if (client.readyState === 1) { // OPEN
            client.send(payload);
          }
        }
      } 
    },

    close(ws) {
      // on disconnect, remove from all rooms
      for (const clients of rooms.values()) {
        clients.delete(ws);
      }
    },
  },
});

console.log("✅ Bun realtime server running on port " + (process.env.PORT || 7860));