diff --git a/admin/server/controllers/systems.js b/admin/server/controllers/systems.js index 9f7f6d7..307e1cb 100644 --- a/admin/server/controllers/systems.js +++ b/admin/server/controllers/systems.js @@ -71,12 +71,14 @@ exports.listSystems = async function (req, res, next) { for (var i = 0; i < stats.length; i++) { sys_stats[stats[i].shortName] = {}; - sys_stats[stats[i].shortName].callTotals = stats[i].callTotals; - sys_stats[stats[i].shortName].uploadErrors = stats[i].uploadErrors; + sys_stats[stats[i].shortName]["uploadErrors"] = stats[i].uploadErrors; + sys_stats[stats[i].shortName]["callTotals"] = stats[i].callTotals; + sys_stats[stats[i].shortName].talkgroupStats= stats[i].talkgroupStats; sys_stats[stats[i].shortName].decodeErrorsFreq = stats[i].decodeErrorsFreq; } + console.log(sys_stats["test"]); res.json({ success: true, systems: returnSys, diff --git a/backend/controllers/calls.js b/backend/controllers/calls.js index e795609..c1889cc 100644 --- a/backend/controllers/calls.js +++ b/backend/controllers/calls.js @@ -1,5 +1,5 @@ -var ObjectID = require('mongodb').ObjectID; +const { ObjectId } = require('mongodb'); var db = require('../db'); var mongoose = require("mongoose"); var { callModel: Call } = require("../models/call"); @@ -110,7 +110,7 @@ async function build_filter(filter_type, code, start_time, direction, shortName, const group = await groupCollection.findOne({ 'shortName': shortName, - '_id': ObjectID.createFromHexString(code) + '_id': ObjectId.createFromHexString(code) }); if (!group) { console.warn("[" + shortName + "] Error - build_filter() group is null " + err); @@ -163,9 +163,9 @@ async function build_filter(filter_type, code, start_time, direction, shortName, exports.get_card = async function (req, res) { var objectId = req.params.id; try { - var o_id = ObjectID.createFromHexString(objectId); + var o_id = ObjectId.createFromHexString(objectId); } catch (err) { - console.warn("Error - /card/:id generating ObjectID " + err); + console.warn("Error - /card/:id generating ObjectId " + err); res.status(500); res.send(JSON.stringify({ error: err, @@ -219,9 +219,9 @@ function package_call(item) { exports.remove_star = async function (req, res, next) { var objectId = req.params.id; try { - var o_id = ObjectID.createFromHexString(objectId); + var o_id = ObjectId.createFromHexString(objectId); } catch (err) { - console.warn("[" + req.params.shortName + "] Error - /remove_star/:id generating ObjectID " + err); + console.warn("[" + req.params.shortName + "] Error - /remove_star/:id generating ObjectId " + err); res.status(500); res.send(JSON.stringify({ success: false, @@ -252,9 +252,9 @@ exports.remove_star = async function (req, res, next) { exports.add_star = async function (req, res, next) { var objectId = req.params.id; try { - var o_id = ObjectID.createFromHexString(objectId); + var o_id = ObjectId.createFromHexString(objectId); } catch (err) { - console.warn("[" + req.params.shortName + "] Error - /add_star/:id generating ObjectID " + err); + console.warn("[" + req.params.shortName + "] Error - /add_star/:id generating ObjectId " + err); res.status(500); res.send(JSON.stringify({ success: false, @@ -286,9 +286,9 @@ exports.add_star = async function (req, res, next) { exports.get_call = async function (req, res) { var objectId = req.params.id; try { - var o_id = ObjectID.createFromHexString(objectId); + var o_id = ObjectId.createFromHexString(objectId); } catch (err) { - console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id generating ObjectID " + err); + console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id generating ObjectId " + err); res.status(500); res.send(JSON.stringify({ success: false, diff --git a/backend/controllers/events.js b/backend/controllers/events.js index a2d0b83..38c96dc 100644 --- a/backend/controllers/events.js +++ b/backend/controllers/events.js @@ -1,8 +1,6 @@ -var ObjectID = require('mongodb').ObjectID; -const { spawn, spawnSync } = require('node:child_process'); +const { ObjectId } = require('mongodb'); +const { spawn } = require('node:child_process'); const https = require('https'); -var db = require('../db'); -var mongoose = require("mongoose"); var Event = require("../models/event"); var Podcast = require("../models/podcast"); var System = require("../models/system"); @@ -14,22 +12,20 @@ var frontend_server = process.env['REACT_APP_FRONTEND_SERVER'] != null ? process const os = require('os'); var fs = require('fs'); -const s3 = require('aws-sdk'); -const { events } = require('../models/event'); +const { PutObjectCommand, S3Client } = require("@aws-sdk/client-s3"); +const { fromIni } = require("@aws-sdk/credential-providers"); var s3_endpoint = process.env['S3_ENDPOINT'] != null ? process.env['S3_ENDPOINT'] : 'https://s3.us-west-1.wasabisys.com'; +var s3_region = process.env['S3_REGION'] != null ? process.env['S3_REGION'] : 'us-west-1'; var s3_bucket = process.env['S3_BUCKET'] != null ? process.env['S3_BUCKET'] : 'openmhz-west'; var s3_profile = process.env['S3_PROFILE'] != null ? process.env['S3_PROFILE'] : 'wasabi-account'; -const s3Endpoint = new s3.Endpoint(s3_endpoint); -var s3Credentials = new s3.SharedIniFileCredentials({ - profile: s3_profile -}); -s3.config.credentials = s3Credentials; -const s3S3 = new s3.S3({ - endpoint: s3Endpoint, - maxRetries: 2 +const client = new S3Client({ + credentials: fromIni({ profile: s3_profile }), + endpoint: s3_endpoint, + region: s3_region, + maxAttempts: 2 }); @@ -105,41 +101,36 @@ const createEventZip = async (folder, filename, zipFolder) => { } -const uploadFile = (zipFile, s3File) => { +const uploadFile = async (zipFile, s3File) => { var s3Src = fs.createReadStream(zipFile); - return new Promise((resolve, reject) => { - const s3Params = { - Bucket: s3_bucket, - Key: s3File, - Body: s3Src, - ACL: 'public-read' - }; - s3S3.upload(s3Params, function (err, data) { - s3Src.destroy(); - - if (err) { - console.error("Event S3 Upload Error " + err); - reject(err); - } else { - resolve("done"); - } - }); + const command = new PutObjectCommand({ + Bucket: s3_bucket, + Key: s3File, + Body: s3Src, + ACL: 'public-read' }); + + try { + await client.send(command); + s3Src.destroy(); + } catch (err) { + console.error("Event S3 Upload Error " + err); + } } const ffmpeg = async (command) => { -// https://stackoverflow.com/questions/68101810/how-to-execute-ffmpeg-commands-synchronously + // https://stackoverflow.com/questions/68101810/how-to-execute-ffmpeg-commands-synchronously return new Promise((resolve, reject) => { const ffmpeg = spawn("/usr/bin/ffmpeg", command); //ffmpeg.once('error', reject); ffmpeg.stderr.on("data", (data) => { console.error(data.toString()); //I'm not sure what debug is - }); + }); ffmpeg.stdout.on("data", (data) => { //console.log(data.toString()); //I'm not sure what debug is - }); + }); ffmpeg.on("exit", (code, signal) => { if (signal) code = signal; @@ -156,11 +147,15 @@ const ffmpeg = async (command) => { }; const escapeMetadata = (input) => { - let result = input.replace(/(\\)/g, '\\\\'); - result=result.replace(/(\;)/g, '\\;'); - result=result.replace(/(\#)/g, '\\#'); - result=result.replace(/(\=)/g, '\\='); - return result; + if (typeof input === 'string') { + let result = input.replace(/(\\)/g, '\\\\'); + result = result.replace(/(\;)/g, '\\;'); + result = result.replace(/(\#)/g, '\\#'); + result = result.replace(/(\=)/g, '\\='); + return result; + } else { + return ""; + } } const createChapters = (event) => { let chapters = ";FFMETADATA1\n"; @@ -204,7 +199,7 @@ const createPodcast = async (tmpEventFolder, podcastFile, event) => { command.push("-acodec"); command.push("copy"); command.push(tmpFile); - console.log("Running command: " + command); + //console.log("Running command: " + command); await ffmpeg(command); @@ -221,7 +216,7 @@ const createPodcast = async (tmpEventFolder, podcastFile, event) => { command.push("-codec"); command.push("copy"); command.push(podcastFile) - console.log("Running command: " + command); + //console.log("Running command: " + command); await ffmpeg(command); } @@ -278,15 +273,15 @@ const packageEvent = (eventId) => { exportEventJson(tmpEventFolder, event); createEventZip(tmpEventFolder, zipFile, eventFolder); await uploadFile(zipFile, s3ZipFile); - + const downloadUrl = s3_endpoint + "/" + s3_bucket + "/" + s3ZipFile; const podcastUrl = s3_endpoint + "/" + s3_bucket + "/" + s3PodcastFile; event.downloadUrl = downloadUrl; event.podcastUrl = podcastUrl; await event.save(); await createPodcast(tmpEventFolder, podcastFile, event); - await uploadFile(podcastFile,s3PodcastFile); - await savePodcast(event,podcastUrl); + await uploadFile(podcastFile, s3PodcastFile); + await savePodcast(event, podcastUrl); console.log("uploaded to: " + podcastUrl); @@ -368,7 +363,7 @@ exports.addNewEvent = async function (req, res, next) { const callIds = req.body.callIds; let objectIds = []; callIds.forEach((id) => { - objectIds.push(new ObjectID(id)); + objectIds.push(new ObjectId(id)); }) event.title = title.replace(/[^a-zA-Z0-9 \.\-\_]/g, ""); diff --git a/backend/controllers/uploads.js b/backend/controllers/uploads.js index 537c7a7..da97ad8 100644 --- a/backend/controllers/uploads.js +++ b/backend/controllers/uploads.js @@ -1,13 +1,10 @@ var path = require('path'); var fs = require('fs'); var sysStats = require("../sys_stats"); -var probe = require('node-ffprobe'); -var mongoose = require("mongoose"); var System = require("../models/system"); var Talkgroup = require("../models/talkgroup"); var { callModel: Call } = require("../models/call"); -var secrets = require("../config/secrets"); -var util = require("util") + const { PutObjectCommand, S3Client } = require("@aws-sdk/client-s3"); const {fromIni} = require("@aws-sdk/credential-providers"); @@ -148,19 +145,19 @@ exports.upload = async function (req, res, next) { console.error(err); } - var wasabiSrc = fs.createReadStream(req.file.path); + var s3Src = fs.createReadStream(req.file.path); const command = new PutObjectCommand({ Bucket: s3_bucket, Key: object_key, - Body: wasabiSrc, + Body: s3Src, ACL: 'public-read' }); try { await client.send(command); - wasabiSrc.destroy(); + s3Src.destroy(); fs.unlink(req.file.path, async (err) => { if (err) { console.error("[" + call.shortName + "]error deleting: " + req.file.path); diff --git a/backend/index.js b/backend/index.js index 7425e34..bccdb8a 100644 --- a/backend/index.js +++ b/backend/index.js @@ -16,7 +16,7 @@ var events = require("./controllers/events"); var config = require('./config/config.json'); var mongoose = require("mongoose"); -var ObjectID = require('mongodb').ObjectID; +const { ObjectId } = require('mongodb'); var db = require('./db'); var System = require("./models/system"); @@ -264,14 +264,14 @@ io.sockets.on('connection', function (client) { delete clients[client.id]; return; } - if (!ObjectID.isValid(data.filterCode)) { + if (!ObjectId.isValid(data.filterCode)) { console.error("Error - Socket - Invalid Group ID: " + data.filterCode); delete clients[client.id]; return; } groupCollection.findOne({ 'shortName': data.shortName.toLowerCase(), - '_id': ObjectID.createFromHexString(data.filterCode) + '_id': ObjectId.createFromHexString(data.filterCode) }, function (err, group) { if (err) { console.warn("[" + data.shortName.toLowerCase() + "] Error - WebSocket Group ID not Found! Error: " + err + " Group ID: " + data.filterCode); diff --git a/backend/sys_stats.js b/backend/sys_stats.js index 8064ceb..4dedee0 100644 --- a/backend/sys_stats.js +++ b/backend/sys_stats.js @@ -262,7 +262,7 @@ exports.shiftStats = async function() { - const query = { shortName: item.shortName}; + const query = { shortName: shortName}; const update = { $set: { "talkgroupStats": talkgroupStats[shortName], "callTotals": callTotals[shortName] }}; const options = {upsert: true}; diff --git a/test.env.example b/test.env.example index c6548be..b7b87a0 100644 --- a/test.env.example +++ b/test.env.example @@ -23,7 +23,3 @@ export REACT_APP_ACCOUNT_SERVER="${PROTOCOL}account.${DOMAIN_NAME}" export REACT_APP_ADMIN_SERVER="${PROTOCOL}admin.${DOMAIN_NAME}" export REACT_APP_COOKIE_DOMAIN=".${DOMAIN_NAME}" -export TWITTER_CONSUMER_KEY="" -export TWITTER_CONSUMER_SECRET="" -export TWITTER_ACCESS_TOKEN_KEY="" -export TWITTER_ACCESS_TOKEN_SECRET=""