// GridTracker Copyright © 2022 GridTracker.org // All rights reserved. // See LICENSE for more information. var g_gtEngineInterval = null; var g_chatRecvFunctions = { uuid: gtChatSetUUID, list: gtChatNewList, info: gtChatUpdateCall, drop: gtChatRemoveCall, mesg: gtChatMessage, o: gtSpotMessage }; var ChatState = Object(); ChatState.none = -1; ChatState.idle = 0; ChatState.connect = 1; ChatState.connecting = 2; ChatState.connected = 3; ChatState.status = 4; ChatState.closed = 5; ChatState.error = 6; var g_gtStateToFunction = { "-1": gtSetIdle, 0: gtCanConnect, 1: gtConnectChat, 2: gtConnecting, 3: gtChatSendUUID, 4: gtStatusCheck, 5: gtInError, 6: gtClosedSocket }; var g_gtChatSocket = null; var g_gtFlagPins = Object(); var g_gtMessages = Object(); var g_gtUnread = Object(); var g_gtIdToCid = Object(); var g_gtCallsigns = Object(); var g_gtSentAwayToCid = Object(); var g_gtState = ChatState.none; var g_gtStatusCount = 0; var g_gtStatusTime = 500; var g_gtMaxChatMessages = 100; var g_gtNeedUsersList = true; var g_gtLiveStatusUpdate = false; var myChatId = 0; var myRoom = 0; var g_gtChatlistChangeCount = 0; var g_gtCurrentMessageCount = 0; function gtConnectChat() { if (g_gtChatSocket != null) { // we should start over g_gtState = ChatState.error; return; } var rnd = parseInt(Math.random() * 10) + 18360; try { g_gtState = ChatState.connecting; g_gtChatSocket = new WebSocket("ws://oams.space:" + rnd); } catch (e) { g_gtState = ChatState.error; return; } g_gtChatSocket.onopen = function () { g_gtState = ChatState.connected; }; g_gtChatSocket.onmessage = function (evt) { if (g_appSettings.gtShareEnable == true) { var jsmesg = false; try { jsmesg = JSON.parse(evt.data); } catch (err) { // bad message, dumping client g_gtState = ChatState.error; return; } if (typeof jsmesg.type == "undefined") { g_gtState = ChatState.error; return; } if (jsmesg.type in g_chatRecvFunctions) { g_chatRecvFunctions[jsmesg.type](jsmesg); } else { g_gtState = ChatState.error; } } }; g_gtChatSocket.onerror = function () { g_gtState = ChatState.error; }; g_gtChatSocket.onclose = function () { g_gtState = ChatState.closed; }; } function gtConnecting() {} function gtInError() { closeGtSocket(); } function gtChatSendClose() { msg = Object(); msg.type = "close"; msg.uuid = g_appSettings.chatUUID; sendGtJson(JSON.stringify(msg)); } function closeGtSocket() { if (g_gtChatSocket != null) { gtChatSendClose(); if (g_gtChatSocket.readyState != WebSocket.CLOSED) g_gtChatSocket.close(); if (g_gtChatSocket.readyState === WebSocket.CLOSED) { g_gtChatSocket = null; g_gtState = ChatState.none; } } else g_gtState = ChatState.none; } function gtClosedSocket() { g_gtChatSocket = null; g_gtState = ChatState.none; } function gtCanConnect() { g_gtState = ChatState.connect; } function gtSetIdle() { g_gtStatusCount = 0; g_gtNeedUsersList = true; g_gtState = ChatState.idle; g_lastGtStatus = ""; } function gtStatusCheck() { if (g_gtStatusCount > 0) { g_gtStatusCount--; } if (g_gtStatusCount == 0 || g_gtLiveStatusUpdate == true) { if (g_gtLiveStatusUpdate == true) { g_gtLiveStatusUpdate = false; } else { g_lastGtStatus = ""; g_gtStatusCount = g_gtStatusTime; } gtChatSendStatus(); } if (g_gtNeedUsersList == true) { g_gtNeedUsersList = false; gtChatGetList(); } } function sendGtJson(json) { if (g_gtChatSocket != null) { if (g_gtChatSocket.readyState === WebSocket.OPEN) { g_gtChatSocket.send(json); } else { if (g_gtChatSocket.readyState === WebSocket.CLOSED) { g_gtState = ChatState.closed; } } } else g_gtState = ChatState.closed; } var g_lastGtStatus = ""; function gtChatSendStatus() { var msg = Object(); msg.type = "status"; msg.uuid = g_appSettings.chatUUID; msg.call = myDEcall; msg.grid = myRawGrid; msg.freq = myRawFreq; msg.mode = myMode; msg.band = myBand; msg.src = "GT"; msg.canmsg = g_appSettings.gtMsgEnable == true; msg.o = g_appSettings.gtSpotEnable == true ? 1 : 0; msg = JSON.stringify(msg); if (msg != g_lastGtStatus) { sendGtJson(msg); g_lastGtStatus = msg; } } function gtChatSendSpots(spotsObject) { var msg = Object(); msg.type = "o"; msg.uuid = g_appSettings.chatUUID; msg.o = spotsObject; msg = JSON.stringify(msg); sendGtJson(msg); } function gtChatRemoveCall(jsmesg) { var id = jsmesg.id; if (id in g_gtIdToCid) { var cid = g_gtIdToCid[id]; if (cid in g_gtFlagPins) { delete g_gtFlagPins[cid].ids[id]; if (Object.keys(g_gtFlagPins[cid].ids).length == 0) { if (g_gtFlagPins[cid].pin != null) { // remove pin from map here if (g_layerSources.gtflags.hasFeature(g_gtFlagPins[cid].pin)) { g_layerSources.gtflags.removeFeature(g_gtFlagPins[cid].pin); } delete g_gtFlagPins[cid].pin; g_gtFlagPins[cid].pin = null; } g_gtFlagPins[cid].live = false; notifyNoChat(cid); if (!(cid in g_gtMessages)) { delete g_gtCallsigns[g_gtFlagPins[cid].call]; delete g_gtFlagPins[cid]; } updateChatWindow(); } } delete g_gtIdToCid[id]; } } function gtChatUpdateCall(jsmesg) { var id = jsmesg.id; var cid = jsmesg.cid; if (cid in g_gtFlagPins) { g_gtFlagPins[cid].ids[id] = true; // Did they move grid location? if (g_gtFlagPins[cid].pin != null) { // remove pin from map here if (g_layerSources.gtflags.hasFeature(g_gtFlagPins[cid].pin)) { g_layerSources.gtflags.removeFeature(g_gtFlagPins[cid].pin); } delete g_gtFlagPins[cid].pin; g_gtFlagPins[cid].pin = null; } } else { g_gtFlagPins[cid] = Object(); g_gtFlagPins[cid].pin = null; g_gtFlagPins[cid].ids = Object(); g_gtFlagPins[cid].ids[id] = true; } g_gtIdToCid[jsmesg.id] = jsmesg.cid; g_gtFlagPins[cid].cid = jsmesg.cid; g_gtFlagPins[cid].call = jsmesg.call; g_gtFlagPins[cid].grid = jsmesg.grid; g_gtFlagPins[cid].freq = jsmesg.freq; g_gtFlagPins[cid].band = jsmesg.band; g_gtFlagPins[cid].mode = jsmesg.mode; g_gtFlagPins[cid].src = jsmesg.src; g_gtFlagPins[cid].canmsg = jsmesg.canmsg; g_gtFlagPins[cid].o = jsmesg.o; g_gtFlagPins[cid].dxcc = callsignToDxcc(jsmesg.call); g_gtFlagPins[cid].live = true; // Make a pin here if (g_gtFlagPins[cid].pin == null) { makeGtPin(g_gtFlagPins[cid]); if (g_gtFlagPins[cid].pin != null) { g_layerSources.gtflags.addFeature(g_gtFlagPins[cid].pin); } } g_gtChatlistChangeCount++; g_gtCallsigns[g_gtFlagPins[cid].call] = cid; updateChatWindow(); } function gtChatGetList() { msg = Object(); msg.type = "list"; msg.uuid = g_appSettings.chatUUID; sendGtJson(JSON.stringify(msg)); } function redrawPins() { clearGtFlags(); for (cid in g_gtFlagPins) { if (g_gtFlagPins[cid].pin != null) { delete g_gtFlagPins[cid].pin; g_gtFlagPins[cid].pin = null; } makeGtPin(g_gtFlagPins[cid]); if (g_gtFlagPins[cid].pin != null) { g_layerSources.gtflags.addFeature(g_gtFlagPins[cid].pin); } } } function makeGtPin(obj) { try { if (obj.pin) { if (g_layerSources.gtflags.hasFeature(obj.pin)) { g_layerSources.gtflags.removeFeature(obj.pin); } delete obj.pin; obj.pin = null; } if (typeof obj.grid == "undefined" || obj.grid == null) return; if (obj.grid.length != 4 && obj.grid.length != 6) return; if (validateGridFromString(obj.grid, null) == false) return; if ( g_appSettings.gtFlagImgSrc == 2 && (obj.mode != myMode || obj.band != myBand) ) { return; } var LL = squareToLatLongAll(obj.grid); var myLonLat = [ LL.lo2 - (LL.lo2 - LL.lo1) / 2, LL.la2 - (LL.la2 - LL.la1) / 2 ]; obj.pin = iconFeature(ol.proj.fromLonLat(myLonLat), g_gtFlagIcon, 100); obj.pin.key = obj.cid; obj.pin.isGtFlag = true; obj.pin.size = 1; } catch (e) {} } function gtChatNewList(jsmesg) { clearGtFlags(); for (var cid in g_gtFlagPins) { g_gtFlagPins[cid].live = false; if (!(cid in g_gtMessages)) { delete g_gtFlagPins[cid]; } } for (var key in jsmesg.data.calls) { var cid = jsmesg.data.cid[key]; var id = jsmesg.data.id[key]; if (id != myChatId) { if (cid in g_gtFlagPins) { g_gtFlagPins[cid].ids[id] = true; } else { g_gtFlagPins[cid] = Object(); g_gtFlagPins[cid].ids = Object(); g_gtFlagPins[cid].ids[id] = true; g_gtFlagPins[cid].pin = null; } g_gtIdToCid[id] = cid; g_gtFlagPins[cid].call = jsmesg.data.calls[key]; g_gtFlagPins[cid].grid = jsmesg.data.grid[key]; g_gtFlagPins[cid].freq = jsmesg.data.freq[key]; g_gtFlagPins[cid].band = jsmesg.data.band[key]; g_gtFlagPins[cid].mode = jsmesg.data.mode[key]; g_gtFlagPins[cid].src = jsmesg.data.src[key]; g_gtFlagPins[cid].cid = cid; g_gtFlagPins[cid].canmsg = jsmesg.data.canmsg[key]; g_gtFlagPins[cid].o = jsmesg.data.o[key]; g_gtFlagPins[cid].dxcc = callsignToDxcc(g_gtFlagPins[cid].call); g_gtFlagPins[cid].live = true; g_gtCallsigns[g_gtFlagPins[cid].call] = cid; makeGtPin(g_gtFlagPins[cid]); if (g_gtFlagPins[cid].pin != null) { g_layerSources.gtflags.addFeature(g_gtFlagPins[cid].pin); } } } g_gtChatlistChangeCount++; updateChatWindow(); } function appendToHistory(cid, jsmesg) { if (!(cid in g_gtMessages)) { g_gtMessages[cid] = Object(); g_gtMessages[cid].history = Array(); } g_gtMessages[cid].history.push(jsmesg); while (g_gtMessages[cid].history.length > g_gtMaxChatMessages) { g_gtMessages[cid].history.shift(); } } function htmlEntities(str) { return String(str) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } function gtChatMessage(jsmesg) { if (g_appSettings.gtMsgEnable == true) { var cid = jsmesg.cid; jsmesg.when = Date.now(); try { jsmesg.msg = new Buffer.from(jsmesg.msg, "base64").toString("utf8"); // eslint-disable-line new-cap jsmesg.msg = htmlEntities(jsmesg.msg); } catch (e) { jsmesg.msg = "Corrupt message recieved"; } if (jsmesg.call != null && jsmesg.call != "" && jsmesg.call != "NOCALL") { appendToHistory(cid, jsmesg); g_gtUnread[cid] = true; g_gtCurrentMessageCount++; if (newChatMessage(cid, jsmesg) == false) alertChatMessage(); if (g_msgSettings.msgAwaySelect == 1 && !(cid in g_gtSentAwayToCid)) { g_gtSentAwayToCid[cid] = true; gtSendMessage( "Away message [ " + g_msgSettings.msgAwayText + " ]", cid ); } } } } function gtSendMessage(message, who) { msg = Object(); msg.type = "mesg"; msg.uuid = g_appSettings.chatUUID; msg.cid = who; msg.msg = new Buffer.from(message).toString("base64"); // eslint-disable-line new-cap sendGtJson(JSON.stringify(msg)); msg.msg = htmlEntities(message); msg.id = 0; msg.when = Date.now(); appendToHistory(who, msg); } function gtChatSendUUID() { var msg = Object(); msg.type = "uuid"; if (g_appSettings.chatUUID != "") msg.uuid = g_appSettings.chatUUID; msg.call = myDEcall; msg.ver = gtShortVersion; sendGtJson(JSON.stringify(msg)); } function gtChatSetUUID(jsmesg) { g_appSettings.chatUUID = jsmesg.uuid; myChatId = jsmesg.id; gtChatSendStatus(); g_gtState = ChatState.status; } function gtChatStateMachine() { if ( g_appSettings.gtShareEnable == true && g_mapSettings.offlineMode == false ) { var now = timeNowSec(); g_gtStateToFunction[g_gtState](); if (Object.keys(g_gtUnread).length > 0 && now % 2 == 0) { msgImg.style.webkitFilter = "invert(1)"; } else msgImg.style.webkitFilter = ""; if ( g_msgSettings.msgFrequencySelect > 0 && Object.keys(g_gtUnread).length > 0 ) { if (now - g_lastChatMsgAlert > g_msgSettings.msgFrequencySelect * 60) { alertChatMessage(); } } } else { closeGtSocket(); g_gtChatlistChangeCount = 0; g_lastGtStatus = ""; } } function gtSpotMessage(jsmesg) { addNewOAMSSpot(jsmesg.cid, jsmesg.db); } function gtChatSystemInit() { g_gtEngineInterval = setInterval(gtChatStateMachine, 1000); } function showGtFlags() { if (g_appSettings.gtFlagImgSrc > 0) { if (g_mapSettings.offlineMode == false) { redrawPins(); g_layerVectors.gtflags.setVisible(true); } else { g_layerVectors.gtflags.setVisible(false); } } else g_layerVectors.gtflags.setVisible(false); } function clearGtFlags() { g_layerSources.gtflags.clear(); } function toggleGtMap() { g_appSettings.gtFlagImgSrc += 1; g_appSettings.gtFlagImgSrc %= 3; gtFlagImg.src = g_gtFlagImageArray[g_appSettings.gtFlagImgSrc]; if (g_spotsEnabled == 1 && g_receptionSettings.mergeSpots == false) return; if (g_appSettings.gtFlagImgSrc > 0) { redrawPins(); g_layerVectors.gtflags.setVisible(true); } else { g_layerVectors.gtflags.setVisible(false); } } function notifyNoChat(id) { if (g_chatWindowHandle != null) { try { g_chatWindowHandle.window.notifyNoChat(id); } catch (e) {} } } function updateChatWindow() { if (g_chatWindowHandle != null) { try { g_chatWindowHandle.window.updateEverything(); } catch (e) {} } } function newChatMessage(id, jsmesg) { var hasFocus = false; if (g_msgSettings.msgActionSelect == 1) showMessaging(); if (g_chatWindowHandle != null) { try { hasFocus = g_chatWindowHandle.window.newChatMessage(id, jsmesg); } catch (e) {} updateChatWindow(); } return hasFocus; } var g_lastChatMsgAlert = 0; function alertChatMessage() { if (g_msgSettings.msgAlertSelect == 1) { // Text to speech speakAlertString(g_msgSettings.msgAlertWord); } if (g_msgSettings.msgAlertSelect == 2) { // Audible playAlertMediaFile(g_msgSettings.msgAlertMedia); } g_lastChatMsgAlert = timeNowSec(); }