kopia lustrzana https://gitlab.com/gridtracker.org/gridtracker
699 wiersze
14 KiB
JavaScript
699 wiersze
14 KiB
JavaScript
// GridTracker Copyright © 2021 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, ">")
|
|
.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();
|
|
}
|