const { createServer } = require("node:http"); const next = require("next"); const { Server } = require("socket.io"); const dev = process.env.NODE_ENV !== "production"; const hostname = process.env.HOSTNAME || "0.0.0.0"; const port = Number(process.env.PORT || 3000); const app = next({ dev, hostname, port }); const handle = app.getRequestHandler(); const roomStates = new Map(); app.prepare().then(() => { const httpServer = createServer((req, res) => handle(req, res)); const io = new Server(httpServer, { path: "/api/socket", cors: { origin: process.env.NEXTAUTH_URL || "http://localhost:3000" } }); io.on("connection", (socket) => { socket.on("room:join", ({ roomSlug, user }) => { if (!roomSlug) return; socket.join(roomSlug); socket.data.roomSlug = roomSlug; socket.data.user = user || "Guest"; socket.emit("room:state", roomStates.get(roomSlug) || null); socket.to(roomSlug).emit("presence:join", { user: socket.data.user }); }); socket.on("media:set", (payload) => updateRoom(socket, "media:set", payload)); socket.on("playback:play", (payload) => updateRoom(socket, "playback:play", payload)); socket.on("playback:pause", (payload) => updateRoom(socket, "playback:pause", payload)); socket.on("playback:seek", (payload) => updateRoom(socket, "playback:seek", payload)); socket.on("chat:message", (payload) => relayRoom(socket, "chat:message", payload)); socket.on("disconnect", () => { if (socket.data.roomSlug) { socket.to(socket.data.roomSlug).emit("presence:leave", { user: socket.data.user || "Guest" }); } }); }); function relayRoom(socket, event, payload) { const roomSlug = socket.data.roomSlug; if (!roomSlug) return; io.to(roomSlug).emit(event, { ...payload, user: socket.data.user || "Guest", at: Date.now() }); } function updateRoom(socket, event, payload) { const roomSlug = socket.data.roomSlug; if (!roomSlug) return; const previous = roomStates.get(roomSlug) || {}; const nextState = { ...previous, ...payload, lastEvent: event, updatedBy: socket.data.user || "Guest", updatedAt: Date.now() }; roomStates.set(roomSlug, nextState); io.to(roomSlug).emit(event, nextState); } httpServer.listen(port, hostname, () => { console.log(`WatchLink ready on http://${hostname}:${port}`); }); });