import type { ServerWebSocket } from "bun"; import { callTicket, completeTicket, getCurrentTicket, getDisplayTickets, getLogEntries, getTicket, noShowTicket } from "./redis"; let IP_TO_ROOMS: Record = {}; const iprooms = await Bun.file("./iprooms.csv").text(); const lines = iprooms.split("\n"); for (const line of lines.slice(1)) { const [ip, room] = line.split(","); if (ip && room) { IP_TO_ROOMS[ip.trim()] = room.trim(); } } export let displaySockets: ServerWebSocket[] = []; export async function broadcastDisplayUpdate() { for (const ws of displaySockets) { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: "display", tickets: await getDisplayTickets() })); } } } Bun.serve({ fetch(req, server) { // upgrade the request to a WebSocket if (server.upgrade(req)) { return; // do not return a Response } return new Response("Upgrade failed", { status: 500 }); }, websocket: { async message(ws, message) { console.log("Received message:", message); const data = JSON.parse(message.toString()); if (data.type === "hello") {} else if (data.type === "my-room") { console.log("Client requested room for IP:", ws.remoteAddress); const room = IP_TO_ROOMS[ws.remoteAddress]; if (!room) { return void ws.send(JSON.stringify({ type: "error", code: -1, message: "No room" })); } ws.send(JSON.stringify({ type: "my-room", room }) ); // } else if (data.type === "create-ticket") { // const ticket = await getTicket(data.ticket); // if(!ticket || ticket.status == "completed" || ticket.status == "no-show") { // await createTicket(data.ticket); // ws.send(JSON.stringify({ type: "create-ticket", status: "created", ticket, num: data.ticket }) ); // return; // } // ws.send(JSON.stringify({ type: "error", code: -2, message: "Ticket already exists and is not completed or no-show", ticket, num: data.ticket })); } else if (data.type === "call-ticket") { // const ticket = await getTicket(data.ticket); // if(!ticket || ticket.status == "completed" || ticket.status == "no-show") { // return void ws.send(JSON.stringify({ type: "error", code: -3, message: "Ticket does not exist or is completed or no-show", ticket, num: data.ticket, room: data.room }) ); // } await callTicket(data.ticket, data.room); ws.send(JSON.stringify({ type: "call-ticket", status: "called", ticket: await getTicket(data.ticket), num: data.ticket, room: data.room }) ); await broadcastDisplayUpdate(); } else if (data.type === "complete-ticket") { const ticket = await getTicket(data.ticket); if(ticket?.status !== "called") { await completeTicket(data.ticket); await broadcastDisplayUpdate(); return void ws.send(JSON.stringify({ type: "complete-ticket", status: "skipped", ticket, num: data.ticket }) ); } // // Check how long since called // const calledDate = new Date(ticket.calledDate || "1970-01-01T00:00:00.000Z"); // const now = new Date(); // const diff = now.getTime() - calledDate.getTime(); // if(diff < 5 * 60 * 1000) { // 5 minutes // // Mark as no-show // await noShowTicket(data.ticket); // await broadcastDisplayUpdate(); // return void ws.send(JSON.stringify({ type: "complete-ticket", status: "no-show", ticket, num: data.ticket })); // } await completeTicket(data.ticket); ws.send(JSON.stringify({ type: "complete-ticket", status: "completed", ticket, num: data.ticket })); await broadcastDisplayUpdate(); } else if (data.type === "no-show") { const ticket = await getTicket(data.ticket); if(!ticket) { return; } // // Check how long since called // const calledDate = new Date(ticket.calledDate || "1970-01-01T00:00:00.000Z"); // const now = new Date(); // const diff = now.getTime() - calledDate.getTime(); // if(diff < 5 * 60 * 1000) { // 5 minutes // // Mark as no-show // await noShowTicket(data.ticket); // await broadcastDisplayUpdate(); // return void ws.send(JSON.stringify({ type: "complete-ticket", status: "no-show", ticket, num: data.ticket })); // } await noShowTicket(data.ticket); ws.send(JSON.stringify({ type: "complete-ticket", status: "no-show", ticket, num: data.ticket })); await broadcastDisplayUpdate(); } else if (data.type === "get-log") { const log = await getLogEntries(); ws.send(JSON.stringify({ type: "log", log })); } else if (data.type === "get-ticket") { const ticket = await getTicket(data.ticket); ws.send(JSON.stringify({ type: "ticket", ticket, num: data.ticket })); } else if (data.type === "get-current-ticket") { const ticket = await getCurrentTicket(data.room); ws.send(JSON.stringify({ type: "current-ticket", ...ticket, room: data.room })); } else if (data.type == "display") { if(!displaySockets.includes(ws)) { displaySockets.push(ws); console.log("Added display socket. Total:", displaySockets.length); ws.send(JSON.stringify({ type: "display", tickets: await getDisplayTickets() })); } } }, // a message is received open(ws) { console.log("WebSocket opened"); ws.send(JSON.stringify({ type: "hello" })); }, // a socket is opened close(ws, code, message) { console.log("WebSocket closed"); }, // a socket is closed drain(ws) { }, // the socket is ready to receive more data } });