2023-09-12 15:52:16 +00:00
|
|
|
const path = require("path");
|
|
|
|
const fs = require("fs");
|
|
|
|
|
2023-09-20 04:46:37 +00:00
|
|
|
const { v4: uuidv4 } = require("uuid");
|
|
|
|
|
2023-09-12 15:52:16 +00:00
|
|
|
// pinia store setup
|
2023-10-03 13:15:17 +00:00
|
|
|
import { setActivePinia } from "pinia";
|
|
|
|
import pinia from "../store/index";
|
2023-09-12 15:52:16 +00:00
|
|
|
setActivePinia(pinia);
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
import { useChatStore } from "../store/chatStore.js";
|
2023-09-12 15:52:16 +00:00
|
|
|
const chat = useChatStore(pinia);
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
import { useStateStore } from "../store/stateStore.js";
|
|
|
|
const state = useStateStore(pinia);
|
|
|
|
|
2023-10-21 10:11:06 +00:00
|
|
|
import { sendMessage, sendBroadcastChannel } from "./sock.js";
|
2023-10-15 07:57:35 +00:00
|
|
|
import { displayToast } from "./popupHandler.js";
|
2023-09-20 04:46:37 +00:00
|
|
|
|
2023-10-08 07:57:03 +00:00
|
|
|
|
|
|
|
//const FD = require("./src/js/freedata.js");
|
|
|
|
import {btoa_FD} from "./freedata.js"
|
|
|
|
|
2023-09-20 04:46:37 +00:00
|
|
|
|
|
|
|
// split character
|
|
|
|
const split_char = "0;1;";
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
// define default message object
|
|
|
|
interface Attachment {
|
|
|
|
content_type: string;
|
|
|
|
data: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface messageDefaultObject {
|
|
|
|
command: string;
|
|
|
|
hmac_signed: boolean;
|
|
|
|
percent: number;
|
|
|
|
bytesperminute: number;
|
|
|
|
is_new: boolean;
|
|
|
|
_id: string;
|
|
|
|
timestamp: number;
|
|
|
|
dxcallsign: string;
|
|
|
|
dxgrid: string;
|
|
|
|
msg: string;
|
|
|
|
checksum: string;
|
|
|
|
type: string;
|
|
|
|
status: string;
|
|
|
|
attempt: number;
|
|
|
|
uuid: string;
|
|
|
|
duration: number;
|
|
|
|
nacks: number;
|
|
|
|
speed_list: string;
|
|
|
|
broadcast_sender?: string; // optional for broadcasts
|
|
|
|
|
|
|
|
_attachments: {
|
|
|
|
[filename: string]: Attachment;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface beaconDefaultObject{
|
|
|
|
command: string;
|
|
|
|
is_new: boolean;
|
|
|
|
_id: string;
|
|
|
|
timestamp: number;
|
|
|
|
dxcallsign: string;
|
|
|
|
dxgrid: string;
|
|
|
|
type: string;
|
|
|
|
status: string;
|
|
|
|
uuid: string;
|
|
|
|
snr: string;
|
|
|
|
}
|
|
|
|
|
2023-09-12 15:52:16 +00:00
|
|
|
// ---- MessageDB
|
|
|
|
try {
|
|
|
|
var PouchDB = require("pouchdb");
|
|
|
|
} catch (err) {
|
|
|
|
console.log(err);
|
|
|
|
/*
|
|
|
|
This is a fix for raspberryPi where we get an error when loading pouchdb because of
|
|
|
|
leveldown package isnt running on ARM devices.
|
|
|
|
pouchdb-browser does not depend on leveldb and seems to be working.
|
|
|
|
*/
|
|
|
|
console.log("using pouchdb-browser fallback");
|
|
|
|
var PouchDB = require("pouchdb-browser");
|
|
|
|
}
|
|
|
|
|
|
|
|
PouchDB.plugin(require("pouchdb-find"));
|
|
|
|
//PouchDB.plugin(require('pouchdb-replication'));
|
|
|
|
PouchDB.plugin(require("pouchdb-upsert"));
|
|
|
|
|
|
|
|
// https://stackoverflow.com/a/26227660
|
2023-10-08 08:33:54 +00:00
|
|
|
if(typeof process.env["APPDATA"] !== "undefined"){
|
|
|
|
var appDataFolder = process.env["APPDATA"]
|
|
|
|
console.log(appDataFolder)
|
|
|
|
|
|
|
|
} else {
|
2023-10-20 18:56:52 +00:00
|
|
|
var appDataFolder: string;
|
2023-10-20 17:02:40 +00:00
|
|
|
|
|
|
|
switch (process.platform) {
|
|
|
|
case "darwin":
|
|
|
|
appDataFolder = process.env["HOME"] + "/Library/Application Support";
|
|
|
|
console.log(appDataFolder);
|
|
|
|
break;
|
|
|
|
case "linux":
|
|
|
|
appDataFolder = process.env["HOME"] + "/.config";
|
|
|
|
console.log(appDataFolder);
|
|
|
|
break;
|
|
|
|
case "win32":
|
|
|
|
appDataFolder = "undefined";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
appDataFolder = "undefined";
|
|
|
|
break;
|
2023-10-08 08:33:54 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-20 18:56:52 +00:00
|
|
|
console.log("loading chat database...")
|
|
|
|
console.log("appdata folder:" + appDataFolder)
|
2023-09-12 15:52:16 +00:00
|
|
|
var configFolder = path.join(appDataFolder, "FreeDATA");
|
2023-10-20 18:56:52 +00:00
|
|
|
console.log("config folder:" + configFolder)
|
2023-09-12 15:52:16 +00:00
|
|
|
|
|
|
|
var chatDB = path.join(configFolder, "chatDB");
|
2023-10-20 18:56:52 +00:00
|
|
|
console.log("database path:" + chatDB)
|
|
|
|
|
2023-09-12 15:52:16 +00:00
|
|
|
var db = new PouchDB(chatDB);
|
|
|
|
|
|
|
|
/* -------- CREATE DATABASE INDEXES */
|
|
|
|
createChatIndex();
|
|
|
|
|
2023-10-15 07:57:35 +00:00
|
|
|
/* -------- RUN A DATABASE CLEANUP ON STARTUP */
|
2023-10-17 13:47:30 +00:00
|
|
|
//dbClean()
|
2023-10-15 07:57:35 +00:00
|
|
|
|
2023-10-17 13:47:30 +00:00
|
|
|
updateAllChat(true)
|
2023-10-15 07:57:35 +00:00
|
|
|
|
|
|
|
|
2023-09-20 12:06:16 +00:00
|
|
|
// create callsign set for storing unique callsigns
|
2023-10-03 13:15:17 +00:00
|
|
|
chat.callsign_list = new Set();
|
2023-09-12 15:52:16 +00:00
|
|
|
|
2023-09-27 14:55:57 +00:00
|
|
|
// function for creating a new broadcast
|
2023-10-03 13:15:17 +00:00
|
|
|
export function newBroadcast(broadcastChannel, chatmessage) {
|
|
|
|
var mode = "";
|
|
|
|
var frames = "";
|
|
|
|
var data = "";
|
2023-10-20 17:02:40 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
var file = "";
|
|
|
|
var filetype = "text";
|
|
|
|
var filename = "";
|
2023-10-20 17:02:40 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
var file_checksum = ""; //crc32(file).toString(16).toUpperCase();
|
|
|
|
var checksum = "";
|
|
|
|
var message_type = "broadcast_transmit";
|
|
|
|
var command = "";
|
|
|
|
|
|
|
|
var timestamp = Math.floor(Date.now() / 1000);
|
|
|
|
var uuid = uuidv4();
|
|
|
|
// TODO: Not sure what this uuid part is needed for ...
|
|
|
|
let uuidlast = uuid.lastIndexOf("-");
|
|
|
|
uuidlast += 1;
|
|
|
|
if (uuidlast > 0) {
|
|
|
|
uuid = uuid.substring(uuidlast);
|
|
|
|
}
|
|
|
|
// slice uuid for reducing overhead
|
|
|
|
uuid = uuid.slice(-4);
|
|
|
|
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
let newChatObj: messageDefaultObject = {
|
|
|
|
command: "broadcast",
|
|
|
|
hmac_signed: false,
|
|
|
|
percent: 0,
|
|
|
|
bytesperminute: 0, // You need to assign a value here
|
|
|
|
is_new: false,
|
|
|
|
_id: uuid,
|
|
|
|
timestamp: timestamp,
|
|
|
|
dxcallsign: broadcastChannel,
|
|
|
|
dxgrid: "null",
|
|
|
|
msg: chatmessage,
|
|
|
|
checksum: file_checksum,
|
|
|
|
type: message_type,
|
|
|
|
status: "transmitting",
|
|
|
|
attempt: 1,
|
|
|
|
uuid: uuid,
|
|
|
|
duration: 0,
|
|
|
|
nacks: 0,
|
|
|
|
speed_list: "null",
|
|
|
|
_attachments: {
|
2023-10-03 13:15:17 +00:00
|
|
|
[filename]: {
|
|
|
|
content_type: filetype,
|
2023-10-08 07:57:03 +00:00
|
|
|
data: btoa_FD(file),
|
2023-10-20 17:02:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-27 14:55:57 +00:00
|
|
|
|
2023-10-21 10:11:06 +00:00
|
|
|
//sendMessage(newChatObj)
|
|
|
|
sendBroadcastChannel(newChatObj)
|
2023-10-18 12:29:51 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
addObjToDatabase(newChatObj);
|
2023-09-27 14:55:57 +00:00
|
|
|
}
|
|
|
|
|
2023-09-20 12:06:16 +00:00
|
|
|
// function for creating a new message
|
2023-10-03 13:15:17 +00:00
|
|
|
export function newMessage(
|
|
|
|
dxcallsign,
|
|
|
|
chatmessage,
|
|
|
|
chatFile,
|
|
|
|
chatFileName,
|
|
|
|
chatFileSize,
|
|
|
|
chatFileType,
|
|
|
|
) {
|
|
|
|
var mode = "";
|
|
|
|
var frames = "";
|
|
|
|
var data = "";
|
2023-10-20 17:02:40 +00:00
|
|
|
var filename = "";
|
|
|
|
var filetype = "";
|
|
|
|
var file=""
|
2023-10-03 13:15:17 +00:00
|
|
|
if (typeof chatFile !== "undefined") {
|
2023-10-20 17:02:40 +00:00
|
|
|
file = chatFile;
|
|
|
|
filetype = chatFileType;
|
|
|
|
filename = chatFileName;
|
2023-10-03 13:15:17 +00:00
|
|
|
} else {
|
2023-10-20 17:02:40 +00:00
|
|
|
file = "";
|
|
|
|
filetype = "text";
|
|
|
|
filename = "";
|
2023-10-03 13:15:17 +00:00
|
|
|
}
|
|
|
|
var file_checksum = ""; //crc32(file).toString(16).toUpperCase();
|
|
|
|
var checksum = "";
|
|
|
|
var message_type = "transmit";
|
|
|
|
var command = "";
|
|
|
|
|
|
|
|
var timestamp = Math.floor(Date.now() / 1000);
|
|
|
|
var uuid = uuidv4();
|
|
|
|
// TODO: Not sure what this uuid part is needed for ...
|
|
|
|
let uuidlast = uuid.lastIndexOf("-");
|
|
|
|
uuidlast += 1;
|
|
|
|
if (uuidlast > 0) {
|
|
|
|
uuid = uuid.substring(uuidlast);
|
|
|
|
}
|
|
|
|
// slice uuid for reducing overhead
|
|
|
|
uuid = uuid.slice(-8);
|
|
|
|
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
let newChatObj: messageDefaultObject = {
|
|
|
|
command: "msg",
|
|
|
|
hmac_signed: false,
|
|
|
|
percent: 0,
|
|
|
|
bytesperminute: 0, // You need to assign a value here
|
|
|
|
is_new: false,
|
|
|
|
_id: uuid,
|
|
|
|
timestamp: timestamp,
|
|
|
|
dxcallsign: dxcallsign,
|
|
|
|
dxgrid: "null",
|
|
|
|
msg: chatmessage,
|
|
|
|
checksum: file_checksum,
|
|
|
|
type: message_type,
|
|
|
|
status: "transmitting",
|
|
|
|
attempt: 1,
|
|
|
|
uuid: uuid,
|
|
|
|
duration: 0,
|
|
|
|
nacks: 0,
|
|
|
|
speed_list: "null",
|
|
|
|
_attachments: {
|
2023-10-03 13:15:17 +00:00
|
|
|
[filename]: {
|
|
|
|
content_type: filetype,
|
2023-10-20 17:02:40 +00:00
|
|
|
data: btoa_FD(file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2023-09-20 04:46:37 +00:00
|
|
|
|
2023-10-18 12:29:51 +00:00
|
|
|
sendMessage(newChatObj);
|
2023-10-03 13:15:17 +00:00
|
|
|
addObjToDatabase(newChatObj);
|
2023-09-20 04:46:37 +00:00
|
|
|
}
|
|
|
|
|
2023-09-30 19:57:23 +00:00
|
|
|
// function for creating a list, accessible by callsign
|
2023-10-03 13:15:17 +00:00
|
|
|
function sortChatList() {
|
|
|
|
// Create an empty object to store the reordered data dynamically
|
|
|
|
var reorderedData = {};
|
|
|
|
var jsonObjects = chat.unsorted_chat_list;
|
|
|
|
// Iterate through the list of JSON objects and reorder them dynamically
|
|
|
|
jsonObjects.forEach((obj) => {
|
|
|
|
var dxcallsign = obj.dxcallsign;
|
|
|
|
if (dxcallsign) {
|
|
|
|
if (!reorderedData[dxcallsign]) {
|
|
|
|
reorderedData[dxcallsign] = [];
|
|
|
|
}
|
|
|
|
reorderedData[dxcallsign].push(obj);
|
2023-10-19 03:55:24 +00:00
|
|
|
|
|
|
|
reorderedData[dxcallsign] = reorderedData[dxcallsign].sort(sortByProperty("timestamp"));
|
2023-10-03 13:15:17 +00:00
|
|
|
}
|
|
|
|
});
|
2023-10-19 03:55:24 +00:00
|
|
|
//console.log(reorderedData["2LS-0"])
|
2023-10-03 13:15:17 +00:00
|
|
|
return reorderedData;
|
2023-09-12 20:49:41 +00:00
|
|
|
}
|
2023-09-12 15:52:16 +00:00
|
|
|
|
2023-10-19 03:55:24 +00:00
|
|
|
//https://medium.com/@asadise/sorting-a-json-array-according-one-property-in-javascript-18b1d22cd9e9
|
|
|
|
function sortByProperty(property){
|
|
|
|
return function(a,b){
|
|
|
|
if(a[property] > b[property])
|
|
|
|
return 1;
|
|
|
|
else if(a[property] < b[property])
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2023-10-18 19:19:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
export function getMessageAttachment(id) {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const findResult = await db.find({
|
|
|
|
selector: {
|
|
|
|
_id: id,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const getResult = await db.get(findResult.docs[0]._id, {
|
|
|
|
attachments: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
let obj = getResult;
|
|
|
|
let filename = Object.keys(obj._attachments)[0];
|
|
|
|
let filetype = obj._attachments[filename].content_type;
|
|
|
|
let file = obj._attachments[filename].data;
|
|
|
|
resolve([filename, filetype, file]);
|
|
|
|
} catch (err) {
|
|
|
|
console.log(err);
|
|
|
|
reject(false); // Reject the Promise if there's an error
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-09-22 21:21:44 +00:00
|
|
|
//repeat a message
|
2023-10-03 13:15:17 +00:00
|
|
|
export function repeatMessageTransmission(id) {
|
2023-10-14 13:32:30 +00:00
|
|
|
// 1. get message object by ID
|
|
|
|
// 2. Upsert Attempts
|
|
|
|
// 3. send message
|
2023-10-18 12:29:51 +00:00
|
|
|
|
|
|
|
db.find({
|
|
|
|
selector: {
|
|
|
|
_id: id,
|
|
|
|
},
|
|
|
|
}).then(function (result){
|
|
|
|
console.log(result)
|
|
|
|
let obj = result.docs[0]
|
|
|
|
console.log(obj)
|
|
|
|
obj.attempt += 1
|
|
|
|
databaseUpsert(obj.uuid, "attempt", obj.attempt);
|
|
|
|
updateUnsortedChatListEntry(obj.uuid, "attempt", obj.attempt);
|
|
|
|
sendMessage(obj)
|
|
|
|
}).catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
2023-09-22 21:21:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// delete a message from databse and gui
|
2023-10-03 13:15:17 +00:00
|
|
|
export function deleteMessageFromDB(id) {
|
|
|
|
console.log("deleting: " + id);
|
|
|
|
db.get(id).then(function (doc) {
|
|
|
|
db.remove(doc);
|
|
|
|
});
|
|
|
|
|
|
|
|
// overwrote unsorted chat list by filtering if not ID
|
|
|
|
chat.unsorted_chat_list = chat.unsorted_chat_list.filter(
|
|
|
|
(entry) => entry.uuid !== id,
|
|
|
|
);
|
|
|
|
|
|
|
|
// and finally generate our sorted chat list, which is the key store for chat gui rendering
|
|
|
|
// the removed entry should be removed now from gui
|
|
|
|
chat.sorted_chat_list = sortChatList();
|
2023-09-22 21:21:44 +00:00
|
|
|
}
|
2023-09-12 15:52:16 +00:00
|
|
|
|
2023-10-15 07:57:35 +00:00
|
|
|
|
|
|
|
//Function to clean old beacons and optimize database
|
|
|
|
async function dbClean() {
|
|
|
|
//Only keep the most x latest days of beacons
|
|
|
|
let beaconKeep = 4;
|
|
|
|
let itemCount = 0;
|
|
|
|
let timestampPurge = Math.floor(
|
|
|
|
(Date.now() - beaconKeep * 24 * 60 * 60 * 1000) / 1000,
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
//Items to purge from database
|
|
|
|
var purgeFilter = [
|
|
|
|
{ type: "beacon" },
|
|
|
|
{ type: "ping-ack" },
|
|
|
|
{ type: "ping" },
|
2023-10-18 11:45:57 +00:00
|
|
|
{ type: "request" },
|
|
|
|
{ type: "response" },
|
2023-10-15 07:57:35 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
await db
|
|
|
|
.find({
|
|
|
|
selector: {
|
|
|
|
$and: [{ timestamp: { $lt: timestampPurge } }, { $or: purgeFilter }],
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(async function (result) {
|
|
|
|
//console.log("Purging " + result.docs.length + " beacons received before " + timestampPurge);
|
|
|
|
itemCount = result.docs.length;
|
|
|
|
result.docs.forEach(async function (item) {
|
|
|
|
await deleteMessageFromDB(item._id)
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
//Compact database
|
|
|
|
await db.compact();
|
|
|
|
|
2023-10-17 13:47:30 +00:00
|
|
|
|
2023-10-15 07:57:35 +00:00
|
|
|
|
|
|
|
let message = "Database maintenance is complete"
|
|
|
|
displayToast("info", "bi bi-info-circle", message, 5000);
|
|
|
|
|
|
|
|
message = "Removed "+itemCount+" items from database"
|
|
|
|
displayToast("info", "bi bi-info-circle", message, 5000);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-02 07:50:52 +00:00
|
|
|
// function to update transmission status
|
2023-10-03 13:15:17 +00:00
|
|
|
export function updateTransmissionStatus(obj) {
|
|
|
|
// update database entries
|
|
|
|
databaseUpsert(obj.uuid, "percent", obj.percent);
|
|
|
|
databaseUpsert(obj.uuid, "bytesperminute", obj.bytesperminute);
|
|
|
|
databaseUpsert(obj.uuid, "status", obj.status);
|
|
|
|
|
2023-10-14 13:32:30 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
// update screen rendering / messages
|
|
|
|
updateUnsortedChatListEntry(obj.uuid, "percent", obj.percent);
|
|
|
|
updateUnsortedChatListEntry(obj.uuid, "bytesperminute", obj.bytesperminute);
|
|
|
|
updateUnsortedChatListEntry(obj.uuid, "status", obj.status);
|
2023-10-14 13:32:30 +00:00
|
|
|
|
2023-10-02 07:50:52 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
export function updateUnsortedChatListEntry(uuid, object, value) {
|
2023-10-14 13:32:30 +00:00
|
|
|
|
|
|
|
var data = getFromUnsortedChatListByUUID(uuid)
|
|
|
|
if(data){
|
|
|
|
data[object] = value;
|
|
|
|
console.log("Entry updated:", data[object]);
|
|
|
|
chat.sorted_chat_list = sortChatList();
|
|
|
|
return data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-10-03 13:15:17 +00:00
|
|
|
for (const entry of chat.unsorted_chat_list) {
|
|
|
|
if (entry.uuid === uuid) {
|
|
|
|
entry[object] = value;
|
|
|
|
console.log("Entry updated:", entry[object]);
|
|
|
|
chat.sorted_chat_list = sortChatList();
|
|
|
|
return entry;
|
2023-10-02 07:50:52 +00:00
|
|
|
}
|
2023-10-03 13:15:17 +00:00
|
|
|
}
|
2023-10-14 13:32:30 +00:00
|
|
|
*/
|
2023-10-02 07:50:52 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
console.log("Entry not updated:", object);
|
|
|
|
return null; // Return null if not found
|
2023-10-02 07:50:52 +00:00
|
|
|
}
|
|
|
|
|
2023-10-14 13:32:30 +00:00
|
|
|
function getFromUnsortedChatListByUUID(uuid){
|
|
|
|
for (const entry of chat.unsorted_chat_list) {
|
|
|
|
if (entry.uuid === uuid) {
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
export function getNewMessagesByDXCallsign(dxcallsign): [number, number, any]{
|
2023-10-18 11:45:57 +00:00
|
|
|
let new_counter = 0
|
|
|
|
let total_counter = 0
|
|
|
|
let item_array = []
|
|
|
|
if (typeof dxcallsign !== 'undefined'){
|
|
|
|
for (const key in chat.sorted_chat_list[dxcallsign]){
|
|
|
|
//console.log(chat.sorted_chat_list[dxcallsign][key])
|
|
|
|
//item_array.push(chat.sorted_chat_list[dxcallsign][key])
|
|
|
|
if(chat.sorted_chat_list[dxcallsign][key].is_new){
|
|
|
|
item_array.push(chat.sorted_chat_list[dxcallsign][key])
|
|
|
|
new_counter += 1
|
2023-10-18 12:29:51 +00:00
|
|
|
|
2023-10-18 11:45:57 +00:00
|
|
|
}
|
|
|
|
total_counter += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [total_counter, new_counter, item_array];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function resetIsNewMessage(uuid, value){
|
|
|
|
databaseUpsert(uuid, "is_new", value)
|
|
|
|
updateUnsortedChatListEntry(uuid, "is_new", value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-14 13:32:30 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
export function databaseUpsert(id, object, value) {
|
|
|
|
db.upsert(id, function (doc) {
|
|
|
|
if (!doc[object]) {
|
2023-10-02 07:50:52 +00:00
|
|
|
doc[object] = value;
|
2023-10-03 13:15:17 +00:00
|
|
|
}
|
|
|
|
doc[object] = value;
|
|
|
|
return doc;
|
|
|
|
})
|
|
|
|
.then(function (res) {
|
2023-10-02 07:50:52 +00:00
|
|
|
// success, res is {rev: '1-xxx', updated: true, id: 'myDocId'}
|
2023-10-03 13:15:17 +00:00
|
|
|
console.log(res);
|
|
|
|
})
|
|
|
|
.catch(function (err) {
|
2023-10-02 07:50:52 +00:00
|
|
|
// error
|
2023-10-03 13:15:17 +00:00
|
|
|
console.log(err);
|
2023-10-02 07:50:52 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-09-20 12:06:16 +00:00
|
|
|
// function for fetching all messages from chat / updating chat
|
2023-10-17 13:47:30 +00:00
|
|
|
export async function updateAllChat(cleanup) {
|
|
|
|
|
|
|
|
// run cleanup if requested
|
|
|
|
if (cleanup) {
|
|
|
|
await dbClean()
|
|
|
|
}
|
2023-09-12 15:52:16 +00:00
|
|
|
//Ensure we create an index before running db.find
|
|
|
|
//We can't rely on the default index existing before we get here...... :'(
|
|
|
|
await db
|
|
|
|
.createIndex({
|
|
|
|
index: {
|
|
|
|
fields: [{ dxcallsign: "asc" }, { timestamp: "asc" }],
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(async function (result) {
|
|
|
|
// handle result
|
|
|
|
await db
|
|
|
|
.find({
|
|
|
|
selector: {
|
|
|
|
$and: [
|
|
|
|
{ dxcallsign: { $exists: true } },
|
|
|
|
{ timestamp: { $exists: true } },
|
2023-10-10 20:21:12 +00:00
|
|
|
//{ $or: chat.chat_filter },
|
2023-09-12 15:52:16 +00:00
|
|
|
],
|
|
|
|
},
|
|
|
|
sort: [{ dxcallsign: "asc" }, { timestamp: "asc" }],
|
|
|
|
})
|
|
|
|
.then(async function (result) {
|
|
|
|
for (var item of result.docs) {
|
2023-10-10 20:45:10 +00:00
|
|
|
const dxcallsign = item.dxcallsign;
|
|
|
|
// Check if dxcallsign already exists as a property in the result object
|
|
|
|
if (!chat.sorted_beacon_list[dxcallsign]) {
|
|
|
|
// If not, initialize it with an empty array for snr values
|
|
|
|
chat.sorted_beacon_list[dxcallsign] = {
|
|
|
|
dxcallsign,
|
|
|
|
snr: [],
|
|
|
|
timestamp: [],
|
|
|
|
};
|
|
|
|
chat.callsign_list.add(dxcallsign);
|
|
|
|
}
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
if (item.type === "beacon") {
|
2023-10-10 20:28:35 +00:00
|
|
|
//console.log(item);
|
2023-10-01 11:24:54 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
// TODO: sort beacon list .... maybe a part for a separate function
|
|
|
|
const jsonData = [item];
|
2023-10-10 20:45:10 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
// Process each JSON item step by step
|
|
|
|
jsonData.forEach((jsonitem) => {
|
|
|
|
const { snr, timestamp } = item;
|
|
|
|
|
|
|
|
// Push the snr value to the corresponding dxcallsign's snr array
|
|
|
|
chat.sorted_beacon_list[dxcallsign].snr.push(snr);
|
|
|
|
chat.sorted_beacon_list[dxcallsign].timestamp.push(timestamp);
|
|
|
|
});
|
2023-09-30 19:57:23 +00:00
|
|
|
} else {
|
2023-10-10 20:45:10 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
chat.unsorted_chat_list.push(item);
|
2023-10-19 03:55:24 +00:00
|
|
|
chat.sorted_chat_list = sortChatList();
|
|
|
|
|
2023-09-30 19:57:23 +00:00
|
|
|
}
|
2023-10-19 03:55:24 +00:00
|
|
|
|
2023-09-12 15:52:16 +00:00
|
|
|
}
|
|
|
|
|
2023-10-19 03:55:24 +00:00
|
|
|
|
2023-09-30 18:30:19 +00:00
|
|
|
|
2023-09-12 15:52:16 +00:00
|
|
|
/*
|
|
|
|
if (typeof result !== "undefined") {
|
|
|
|
for (const item of result.docs) {
|
|
|
|
//await otherwise history will not be in chronological order
|
|
|
|
await db
|
|
|
|
.get(item._id, {
|
|
|
|
attachments: true,
|
|
|
|
})
|
|
|
|
.then(function (item_with_attachments) {
|
|
|
|
update_chat(item_with_attachments);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
function addObjToDatabase(newobj) {
|
|
|
|
console.log(newobj);
|
|
|
|
/*
|
2023-09-20 04:46:37 +00:00
|
|
|
db.upsert(newobj._id, function (doc) {
|
|
|
|
if (!doc._id) {
|
|
|
|
console.log("upsert")
|
|
|
|
console.log(doc)
|
|
|
|
doc = newobj
|
|
|
|
} else {
|
|
|
|
console.log("new...")
|
|
|
|
*/
|
2023-10-03 13:15:17 +00:00
|
|
|
db.post(newobj)
|
|
|
|
.then(function (response) {
|
|
|
|
// handle response
|
|
|
|
console.log("new database entry");
|
|
|
|
console.log(response);
|
2023-10-11 18:39:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (newobj.command === "msg") {
|
|
|
|
chat.unsorted_chat_list.push(newobj);
|
|
|
|
chat.sorted_chat_list = sortChatList();
|
|
|
|
}
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
2023-10-11 18:39:35 +00:00
|
|
|
console.log(newobj);
|
|
|
|
|
|
|
|
// try upserting status in case we tried sending a message to our selfes
|
|
|
|
databaseUpsert(newobj.uuid, "status", newobj.status);
|
|
|
|
updateUnsortedChatListEntry(newobj.uuid, "status", newobj.status);
|
|
|
|
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
});
|
2023-09-20 04:46:37 +00:00
|
|
|
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
/*
|
2023-09-20 04:46:37 +00:00
|
|
|
// upsert footer ...
|
|
|
|
|
|
|
|
}
|
|
|
|
return doc;
|
|
|
|
})
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2023-09-12 15:52:16 +00:00
|
|
|
function createChatIndex() {
|
|
|
|
db.createIndex({
|
|
|
|
index: {
|
|
|
|
fields: [
|
|
|
|
"timestamp",
|
|
|
|
"uuid",
|
|
|
|
"dxcallsign",
|
|
|
|
"dxgrid",
|
|
|
|
"msg",
|
|
|
|
"checksum",
|
|
|
|
"type",
|
|
|
|
"command",
|
|
|
|
"status",
|
|
|
|
"percent",
|
|
|
|
"attempt",
|
|
|
|
"hmac_signed",
|
|
|
|
"bytesperminute",
|
|
|
|
"_attachments",
|
2023-09-20 04:46:37 +00:00
|
|
|
"is_new",
|
2023-10-11 18:39:35 +00:00
|
|
|
"nacks",
|
|
|
|
"duration",
|
|
|
|
"speed_list"
|
2023-09-12 15:52:16 +00:00
|
|
|
],
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(function (result) {
|
|
|
|
// handle result
|
|
|
|
console.log(result);
|
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
|
|
|
}
|
2023-09-14 19:45:07 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
export function deleteChatByCallsign(callsign) {
|
|
|
|
chat.callsign_list.delete(callsign);
|
2023-10-20 17:02:40 +00:00
|
|
|
// @ts-expect-error
|
2023-10-03 13:15:17 +00:00
|
|
|
delete chat.unsorted_chat_list.callsign;
|
|
|
|
delete chat.sorted_chat_list.callsign;
|
2023-09-14 19:45:07 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
deleteFromDatabaseByCallsign(callsign);
|
2023-09-14 19:45:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 12:29:51 +00:00
|
|
|
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
function deleteFromDatabaseByCallsign(callsign) {
|
|
|
|
db.find({
|
|
|
|
selector: {
|
|
|
|
dxcallsign: callsign,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(function (result) {
|
|
|
|
// handle result
|
|
|
|
if (typeof result !== "undefined") {
|
|
|
|
result.docs.forEach(function (item) {
|
|
|
|
console.log(item);
|
|
|
|
db.get(item._id)
|
|
|
|
.then(function (doc) {
|
|
|
|
db.remove(doc)
|
2023-09-14 19:45:07 +00:00
|
|
|
.then(function (doc) {
|
2023-10-17 13:47:30 +00:00
|
|
|
updateAllChat(false);
|
2023-10-03 13:15:17 +00:00
|
|
|
return true;
|
2023-09-14 19:45:07 +00:00
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
2023-10-03 13:15:17 +00:00
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
2023-09-14 19:45:07 +00:00
|
|
|
});
|
|
|
|
});
|
2023-10-03 13:15:17 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(function (err) {
|
|
|
|
console.log(err);
|
|
|
|
});
|
2023-09-20 04:46:37 +00:00
|
|
|
}
|
|
|
|
|
2023-09-30 18:30:19 +00:00
|
|
|
// function for handling a received beacon
|
2023-10-03 13:15:17 +00:00
|
|
|
export function newBeaconReceived(obj) {
|
|
|
|
/*
|
2023-09-30 18:30:19 +00:00
|
|
|
{
|
2023-10-20 11:47:42 +00:00
|
|
|
"freedata": "modem-message",
|
2023-09-30 18:30:19 +00:00
|
|
|
"beacon": "received",
|
|
|
|
"uuid": "12741312-3dbb-4a53-b0cc-100f6c930ab8",
|
|
|
|
"timestamp": 1696076869,
|
|
|
|
"dxcallsign": "DJ2LS-0",
|
|
|
|
"dxgrid": "JN48CS",
|
|
|
|
"snr": "-2.8",
|
|
|
|
"mycallsign": "DJ2LS-0"
|
|
|
|
}
|
|
|
|
*/
|
2023-10-20 17:02:40 +00:00
|
|
|
let newChatObj: beaconDefaultObject = {
|
|
|
|
command: "beacon",
|
|
|
|
is_new: false,
|
|
|
|
_id: obj["uuid"],
|
|
|
|
timestamp: obj["timestamp"],
|
|
|
|
dxcallsign: obj["dxcallsign"],
|
|
|
|
dxgrid: obj["dxgrid"],
|
|
|
|
type: "beacon",
|
|
|
|
status: obj["beacon"],
|
|
|
|
uuid: obj["uuid"],
|
|
|
|
snr: obj["snr"], // adding the new field
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
|
|
|
|
addObjToDatabase(newChatObj);
|
|
|
|
|
|
|
|
console.log(obj);
|
|
|
|
|
|
|
|
const jsonData = [obj];
|
|
|
|
const dxcallsign = obj.dxcallsign;
|
|
|
|
// Process each JSON item step by step
|
|
|
|
jsonData.forEach((item) => {
|
|
|
|
const { snr, timestamp } = obj;
|
|
|
|
|
|
|
|
// Check if dxcallsign already exists as a property in the result object
|
|
|
|
if (!chat.sorted_beacon_list[dxcallsign]) {
|
|
|
|
// If not, initialize it with an empty array for snr values
|
|
|
|
chat.sorted_beacon_list[dxcallsign] = {
|
|
|
|
dxcallsign,
|
|
|
|
snr: [],
|
|
|
|
timestamp: [],
|
|
|
|
};
|
|
|
|
}
|
2023-10-01 11:24:54 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
// Push the snr value to the corresponding dxcallsign's snr array
|
|
|
|
chat.sorted_beacon_list[dxcallsign].snr.push(snr);
|
|
|
|
chat.sorted_beacon_list[dxcallsign].timestamp.push(timestamp);
|
|
|
|
});
|
2023-09-30 18:30:19 +00:00
|
|
|
}
|
|
|
|
|
2023-09-20 12:06:16 +00:00
|
|
|
// function for handling a received message
|
2023-10-03 13:15:17 +00:00
|
|
|
export function newMessageReceived(message, protocol) {
|
|
|
|
/*
|
2023-09-27 14:55:57 +00:00
|
|
|
|
|
|
|
PROTOCOL
|
2023-10-11 18:26:44 +00:00
|
|
|
{
|
2023-10-20 11:47:42 +00:00
|
|
|
"freedata": "modem-message",
|
2023-10-11 18:26:44 +00:00
|
|
|
"arq": "transmission",
|
|
|
|
"status": "received",
|
|
|
|
"uuid": "5a3caa57-7feb-4436-853d-e341b085350f",
|
|
|
|
"percent": 100,
|
|
|
|
"bytesperminute": 206,
|
|
|
|
"compression": 0.5833333333333334,
|
|
|
|
"timestamp": 1697048385,
|
|
|
|
"finished": 0,
|
|
|
|
"mycallsign": "DJ2LS-0",
|
|
|
|
"dxcallsign": "DJ2LS-0",
|
|
|
|
"dxgrid": "------",
|
|
|
|
"data": "bTA7MTttc2cwOzE7MDsxOzBlNGE3YjQ2MDsxOzE2OTcwNDgzMTkwOzE7dGVzdDMwOzE7MDsxO3RleHQwOzE7",
|
|
|
|
"irs": "False",
|
|
|
|
"hmac_signed": "False",
|
|
|
|
"duration": 44.385897636413574,
|
|
|
|
"nacks": 1,
|
|
|
|
"speed_list": [
|
|
|
|
{
|
|
|
|
"snr": 0,
|
|
|
|
"bpm": 106,
|
|
|
|
"timestamp": 1697048362
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"snr": -6,
|
|
|
|
"bpm": 104,
|
|
|
|
"timestamp": 1697048370
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"snr": -6,
|
|
|
|
"bpm": 81,
|
|
|
|
"timestamp": 1697048370
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"snr": -5.7,
|
|
|
|
"bpm": 161,
|
|
|
|
"timestamp": 1697048378
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"snr": -5.7,
|
|
|
|
"bpm": 133,
|
|
|
|
"timestamp": 1697048379
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"snr": -5.4,
|
|
|
|
"bpm": 206,
|
|
|
|
"timestamp": 1697048385
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"snr": -5.8,
|
|
|
|
"bpm": 179,
|
|
|
|
"timestamp": 1697048391
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
2023-09-20 12:06:16 +00:00
|
|
|
|
2023-09-27 14:55:57 +00:00
|
|
|
MESSAGE; decoded from "data"
|
|
|
|
[
|
|
|
|
0 - protocol type message - "m",
|
|
|
|
1 - type - "msg",
|
|
|
|
2 - checksum "",
|
|
|
|
3 - uuid - "07e2",
|
|
|
|
4 - timestamp - "1695203833",
|
|
|
|
5 - message - "test",
|
|
|
|
6 - file name - "",
|
|
|
|
7 - mime - "plain/text",
|
|
|
|
8 - file - ""
|
|
|
|
]
|
2023-09-20 12:06:16 +00:00
|
|
|
|
|
|
|
|
2023-09-27 14:55:57 +00:00
|
|
|
*/
|
2023-10-03 13:15:17 +00:00
|
|
|
console.log(protocol);
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
let newChatObj: messageDefaultObject = {
|
|
|
|
command: "msg",
|
|
|
|
hmac_signed: protocol["hmac_signed"],
|
|
|
|
percent: 100,
|
|
|
|
bytesperminute: protocol["bytesperminute"],
|
|
|
|
is_new: true,
|
|
|
|
_id: message[3],
|
|
|
|
timestamp: message[4],
|
|
|
|
dxcallsign: protocol["dxcallsign"],
|
|
|
|
dxgrid: protocol["dxgrid"],
|
|
|
|
msg: message[5],
|
|
|
|
checksum: message[2],
|
|
|
|
type: protocol["status"],
|
|
|
|
status: protocol["status"],
|
|
|
|
attempt: 1,
|
|
|
|
uuid: message[3],
|
|
|
|
duration: protocol["duration"],
|
|
|
|
nacks: protocol["nacks"],
|
|
|
|
speed_list: protocol["speed_list"],
|
|
|
|
_attachments: {
|
2023-10-03 13:15:17 +00:00
|
|
|
[message[6]]: {
|
|
|
|
content_type: message[7],
|
2023-10-20 17:02:40 +00:00
|
|
|
data: btoa_FD(message[8])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-20 12:06:16 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
// some tweaks for broadcasts
|
|
|
|
if (protocol.fec == "broadcast") {
|
|
|
|
newChatObj.broadcast_sender = protocol["dxcallsign"];
|
|
|
|
newChatObj.type = "broadcast_received";
|
|
|
|
}
|
2023-09-20 12:06:16 +00:00
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
addObjToDatabase(newChatObj);
|
2023-09-20 12:06:16 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
export function setStateFailed() {
|
|
|
|
state.arq_seconds_until_finish = 0;
|
|
|
|
state.arq_seconds_until_timeout = 180;
|
|
|
|
state.arq_seconds_until_timeout_percent = 100;
|
2023-10-02 18:50:24 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 13:15:17 +00:00
|
|
|
export function setStateSuccess() {
|
|
|
|
state.arq_seconds_until_finish = 0;
|
|
|
|
state.arq_seconds_until_timeout = 180;
|
|
|
|
state.arq_seconds_until_timeout_percent = 100;
|
2023-10-02 18:50:24 +00:00
|
|
|
}
|
2023-09-20 12:06:16 +00:00
|
|
|
|
2023-10-14 13:32:30 +00:00
|
|
|
export function requestMessageInfo(id){
|
|
|
|
|
|
|
|
console.log(id)
|
|
|
|
// id and uuid are the same
|
|
|
|
var data = getFromUnsortedChatListByUUID(id)
|
|
|
|
console.log(data)
|
|
|
|
chat.selectedMessageObject = data
|
|
|
|
|
|
|
|
|
2023-10-20 17:02:40 +00:00
|
|
|
}
|