diff --git a/index.js b/index.js index 2f88830..8467084 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,7 @@ expressWs(app); // Serve static files from the "public" directory app.use(express.static('public')); global.wsConnections = []; - +var roomList = []; // IEM WebSocket app.ws('/iem', (ws, req) => { console.log(`connection from ${req.ip}`); @@ -33,57 +33,116 @@ app.ws('/iem', (ws, req) => { console.log(`disconnected from ${req.ip}`); wsConnections = wsConnections.filter((conn) => conn.ws !== ws); }); - ws.on('message', (msg) => { - const data = JSON.parse(msg); - if (!data.type) return; - switch (data.type) { - case "subscribe": - if (data.channel) { - if (!wsConnections[sock - 1].subs.includes(data.channel)) { - wsConnections[sock - 1].subs.push(data.channel); + try { + ws.on('message', (msg) => { + const data = JSON.parse(msg); + if (!data.type) return; + switch (data.type) { + case "subscribe": + const subscriptionTarget = data.channel || getWFOroom(data.wfo) || "*"; + if (subscriptionTarget === "*") { + wsConnections[sock - 1].subs.push(subscriptionTarget); ws.send(JSON.stringify({ "type": "internal-response", "code": 200, "data": { - "message": `Subscribed to ${data.channel}` + "message": `Subscribed to all channels.` } })); - } else { - ws.send(JSON.stringify({ - "type": "internal-response", - "code": 409, - "data": { - "error": "Already subscribed to this channel." - } - })); - } - } - break; - case "unsubscribe": - if (data.channel) { - if (wsConnections[sock - 1].subs.includes(data.channel)) { - wsConnections[sock - 1].subs = wsConnections[sock - 1].subs.filter((sub) => sub !== data.channel); - ws.send(JSON.stringify({ - "type": "internal-response", - "code": 200, - "data": { - "message": `Unsubscribed from ${data.channel}` - } - })); - } else { + break; + } else if(!roomList.includes(subscriptionTarget)) { ws.send(JSON.stringify({ "type": "internal-response", "code": 404, "data": { - "error": "Not subscribed to this channel." + "error": "Invalid channel." + } + })); + break; + } else { + wsConnections[sock - 1].subs.push(subscriptionTarget); + ws.send(JSON.stringify({ + "type": "internal-response", + "code": 200, + "data": { + "message": `Subscribed to ${subscriptionTarget}` + } + })); + break; + } + case "unsubscribe": + const unsubscribeTarget = data.channel || getWFOroom(data.wfo) || "*"; + if (unsubscribeTarget === "*") { + wsConnections[sock - 1].subs = wsConnections[sock - 1].subs.filter((sub) => sub !== "*"); + ws.send(JSON.stringify({ + "type": "internal-response", + "code": 200, + "data": { + "message": `Unsubscribed from all channels.` + } + })); + break; + } else if(!getWFO(data.channel)) { + ws.send(JSON.stringify({ + "type": "internal-response", + "code": 404, + "data": { + "error": "Invalid channel." + } + })); + break; + } else { + wsConnections[sock - 1].subs = wsConnections[sock - 1].subs.filter((sub) => sub !== unsubscribeTarget); + ws.send(JSON.stringify({ + "type": "internal-response", + "code": 200, + "data": { + "message": `Unsubscribed from ${unsubscribeTarget}` + } + })); + break; + } + case "get-subscriptions": + ws.send(JSON.stringify({ + "type": "internal-response", + "code": 200, + "data": { + "subscriptions": wsConnections[sock - 1].subs + } + })); + break; + case "room-list": + if (roomList.length > 0) { + ws.send(JSON.stringify({ + "type": "room-list", + "code": 200, + "count": roomList.length, + "data": roomList + })); + } else { + ws.send(JSON.stringify({ + "type": "room-list", + "code": 503, + "count": roomList.length, + "data": { + "error": "Room list is currently empty. Please try again later." } })); } - } - break; - } - }); -}); + } + }); + } catch (error) { + console.error(error); + ws.send(JSON.stringify({ + "type": "internal-response", + "code": 500, + "data": { + "error": "Internal server error." + } + })); + } +}) + // Random funcs function toTitleCase(str) { @@ -150,8 +209,11 @@ const getFirstURL = function (string) { // Function to get the room name from the WFO code const getWFOroom = function (code) { + if (typeof code !== 'string') { + return null; + } code = code.toLowerCase(); - if (wfos[code]) { + if (wfos[code] && typeof wfos[code].room === 'string') { return wfos[code].room; } else { return code; @@ -268,6 +330,7 @@ xmpp.on("stanza", (stanza) => { // Join the room //xmpp.send(xml("presence", { to: `${channel.jid}/${channel.name}/${curUUID}` }, xml("item", { role: "visitor" }))); xmpp.send(xml("presence", { to: `${item.attrs.jid}/${curUUID}` }, xml("item", { role: "visitor" }))); + roomList.push(item.attrs.jid.split("@")[0]); }); } } @@ -339,7 +402,7 @@ xmpp.on("stanza", (stanza) => { }); xmpp.on("status", (status) => { - console.log(`${colors.cyan("[INFO]")} XMPP Status: ${status}`); + console.log(`${colors.cyan("[INFO]")} XMPP Status`); // Broadcast a message to all connected WebSocket clients wsConnections.forEach((connection) => { if (connection.ws.readyState === 1) { // Ensure the socket is open