First Commit

This commit is contained in:
Luke Berndt
2020-06-09 22:11:11 -04:00
parent 8f49aa463c
commit 3b0d3f290f
551 changed files with 193130 additions and 2 deletions

View File

@@ -0,0 +1,386 @@
var ObjectID = require('mongodb').ObjectID;
var db = require('../db');
var mongoose = require("mongoose");
var Call = require("../models/call");
var Star = require("../models/star");
var defaultNumResults = 50;
var channels = {};
function get_calls(query, numResults, res) {
var calls = [];
var fields = {
_id: true,
talkgroupNum: true,
path: true,
name: true,
time: true,
srcList: true,
star: true,
len: true,
url: true
};
db.get().collection('calls', function(err, transCollection) {
transCollection.find(query.filter, fields, function(err, cursor) {
if (err) {
console.warn("Error - get_calls() Could not find item " + err + " filter: " + query.filter);
res.send(404, 'Sorry, we cannot find that!');
return;
}
cursor.sort(query.sort_order).limit(numResults).each(function(err, item) {
if (item) {
call = {
_id: item._id.toHexString(),
talkgroupNum: item.talkgroupNum,
url: item.url,
filename: item.path + item.name,
time: item.time,
srcList: item.srcList,
star: item.star,
len: Math.round(item.len)
};
calls.push(call);
} else {
res.contentType('json');
res.send(JSON.stringify({
calls: calls,
direction: query.direction
}));
}
});
});
});
}
function build_filter(filter_type, code, start_time, direction, shortName, numResults, starred, res) {
var filter = {};
var query = {};
var FilterType = {
All: 0,
Talkgroup: 1,
Group: 2,
Unit: 3
};
/* removed to see if it helps queries
if (starred) {
filter.star = {
$gt: 0
};
}*/
if (start_time) {
var start = new Date(start_time);
if (direction == 'newer') {
filter.time = {
$gt: start
};
} else {
filter.time = {
$lt: start
};
}
}
/*
filter.len = {
$gte: -1.0
};*/
var sort_order = {};
if (direction == 'newer') {
sort_order['time'] = 1;
} else {
sort_order['time'] = -1;
}
// make sure the shortName for the system is included in the query
filter.shortName = shortName;
query['direction'] = direction;
query['sort_order'] = sort_order;
if (filter_type) {
if ((filter_type == "group") && code && (code.indexOf(',') == -1)) {
db.get().collection("groups", function(err, groupCollection) {
if (err || !groupCollection) {
console.warn("[" + shortName + "] Error - build_filter() Group Collection does not exist " + err);
res.contentType('json');
res.send(JSON.stringify( {
message: 'That Group ID doesnt exist.'
}));
return;
}
groupCollection.findOne({
'shortName': shortName,
'_id': ObjectID.createFromHexString(code)
}, function(err, group) {
if (err) {
console.warn("[" + shortName + "] Error - build_filter() Group ID does not exist " + err);
res.contentType('json');
res.send(JSON.stringify( {
message: 'That Group ID doesnt exist.'
}));
} else if (!group) {
console.warn("[" + shortName + "] Error - build_filter() group is null " + err);
res.contentType('json');
res.send(JSON.stringify({
message: 'That Group ID doesnt exist.'
}));
} else{
filter.talkgroupNum = {
$in: group.talkgroups
};
query['filter'] = filter;
get_calls(query, numResults, res);
}
});
});
} else {
if ((filter_type == "talkgroup") || (filter_type == "group")) {
if (code) {
var codeArray = code.split(',').map(function(item) {
return parseInt(item, 10);
});
filter.talkgroupNum = {
$in: codeArray
};
}
}
if (filter_type == "unit") {
if (code) {
var codeArray = code.split(',').map(function(item) {
return parseInt(item, 10);
});
filter.srcListv = {
$in: codeArray
};
}
}
query['filter'] = filter;
get_calls(query, numResults, res);
}
} else {
query['filter'] = filter;
get_calls(query, numResults, res);
}
}
exports.get_card = function(req, res) {
var objectId = req.params.id;
try {
var o_id = ObjectID.createFromHexString(objectId);
} catch (err) {
console.warn("Error - /card/:id generating ObjectID " + err);
res.status(500);
res.send(JSON.stringify({
error: err,
"_id": objectId
}));
return;
}
db.get().collection('calls', function(err, transCollection) {
transCollection.findOne({
'_id': o_id
},
function(err, item) {
//console.log(util.inspect(item));
if (item) {
var time = new Date(item.time);
var timeString = time.toLocaleTimeString("en-US");
var dateString = time.toDateString();
res.render('card', {
item: item,
channel: channels[item.talkgroupNum],
time: timeString,
date: dateString
});
} else {
console.warn("Error - /card/:id Could not find Item " + err);
res.send(404, 'Sorry, we cannot find that!');
}
});
});
}
function package_call(item) {
var time = new Date(item.time);
var timeString = time.toLocaleTimeString("en-US");
var dateString = time.toDateString();
call = {
_id: item._id.toHexString(),
shortName: item.shortName,
talkgroupNum: item.talkgroupNum,
filename: item.path + item.name,
url: item.url,
time: item.time,
timeString: timeString,
dateString: dateString,
path: item.path,
name: item.name,
freq: item.freq,
srcList: item.srcList,
freqList: item.freqList,
star: item.star,
len: Math.round(item.len)
};
return call;
}
exports.add_star = function(req, res, next) {
var objectId = req.params.id;
try {
var o_id = ObjectID.createFromHexString(objectId);
} catch (err) {
console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id generating ObjectID " + err);
res.status(500);
res.send(JSON.stringify({
success: false,
message: err,
"_id": objectId
}));
return;
}
Call.findOneAndUpdate({ _id: objectId }, { $inc: { star: 1 } }, {new: true },function(err, item) {
if (err) {
res.status(500);
res.send(JSON.stringify({
success: false,
message: err,
"_id": objectId
}));
} else {
var call = package_call(item);
req.call = call;
res.send(JSON.stringify({
success: true,
call: call
}));
next();
}
})
}
exports.get_call = function(req, res) {
var objectId = req.params.id;
try {
var o_id = ObjectID.createFromHexString(objectId);
} catch (err) {
console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id generating ObjectID " + err);
res.status(500);
res.send(JSON.stringify({
success: false,
error: err,
"_id": objectId
}));
return;
}
db.get().collection('calls', function(err, transCollection) {
transCollection.findOne({
'_id': o_id
},
function(err, item) {
if (item) {
var call = package_call(item);
res.contentType('json');
res.send(JSON.stringify({
success: true,
call: call})
);
} else {
console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id Could not find item " + err + " ID: " + objectId);
res.status(404);
res.send(JSON.stringify({
success: false,
error: err,
"_id": objectId
}));
}
});
});
}
exports.get_latest_calls = function(req, res) {
var filter_code = req.query["filter-code"];
var filter_type = req.query["filter-type"];
var starred = req.query["filter-starred"] === 'true'?true:false;
var short_name = req.params.shortName.toLowerCase();
//console.log("[" + short_name + "] Latest - Call Get Filter code: " + filter_code + " Filter Type: " + filter_type );
build_filter(filter_type, filter_code, null, 'older', short_name, 1, starred, res);
}
exports.get_next_calls = function(req, res) {
var filter_code = req.query["filter-code"];
var filter_type = req.query["filter-type"];
var starred = req.query["filter-starred"] === 'true'?true:false;
var start_time = parseInt(req.query["time"]);
var short_name = req.params.shortName.toLowerCase();
//console.log("[" + short_name + "] Next Calls - time: " + start_time + " Filter code: " + filter_code + " Filter Type: " + filter_type);
build_filter(filter_type, filter_code, start_time, 'newer', short_name, 1, starred, res);
}
exports.get_newer_calls = function(req, res) {
var filter_code = req.query["filter-code"];
var filter_type = req.query["filter-type"];
var starred = req.query["filter-starred"] === 'true'?true:false;
var start_time = parseInt(req.query["time"]);
var short_name = req.params.shortName.toLowerCase();
//console.log("[" + short_name + "] Newer Calls - time: " + start_time + " Filter code: " + filter_code + " Filter Type: " + filter_type );
build_filter(filter_type, filter_code, start_time, 'newer', short_name, defaultNumResults, starred, res);
}
exports.get_older_calls = function(req, res) {
var filter_code = req.query["filter-code"];
var filter_type = req.query["filter-type"];
var starred = req.query["filter-starred"] === 'true'?true:false;
var start_time = parseInt(req.query["time"]);
var short_name = req.params.shortName.toLowerCase();
//console.log("[" + short_name + "] Older Calls - time: " + start_time + " Filter code: " + filter_code + " Filter Type: " + filter_type);
build_filter(filter_type, filter_code, start_time, 'older', short_name, defaultNumResults, starred, res);
}
//Delete this after I fix the iPhone app
exports.get_iphone_calls = function(req, res) {
var filter_code = req.query["filter-code"];
var filter_type = req.query["filter-type"];
var starred = req.query["filter-starred"] === 'true'?true:false;
var start_time = parseInt(req.params.time);
var short_name = req.params.shortName.toLowerCase();
//console.log("[" + short_name + "] iPhone Newer Calls - time: " + start_time + " Filter code: " + filter_code + " Filter Type: " + filter_type);
build_filter(filter_type, filter_code, start_time, 'older', short_name, defaultNumResults, starred, res);
}
exports.get_calls = function(req, res) {
var filter_code = req.query["filter-code"];
var filter_type = req.query["filter-type"];
var starred = req.query["filter-starred"] === 'true'?true:false;
var short_name = req.params.shortName.toLowerCase();
//console.log("[" + short_name + "] Inital Calls - Call Get Filter code: " + filter_code + " Filter Type: " + filter_type);
build_filter(filter_type, filter_code, null, 'older', short_name, defaultNumResults, starred, res);
}

View File

@@ -0,0 +1,12 @@
var db = require('../db');
exports.get_groups = function(req, res) {
db.get().collection('groups', function(err, grp_coll) {
grp_coll.find({
'shortName': req.params.shortName.toLowerCase()
}).toArray(function(err, grp_results) {
res.contentType('json');
res.send(JSON.stringify(grp_results));
});
});
}

View File

@@ -0,0 +1,146 @@
var sources = {};
var pendingSources = {};
var mongo = require('mongodb');
var ObjectID = require('mongodb').ObjectID;
mongo.BSONPure = require('bson').BSONPure;
var BSON = mongo.BSONPure;
function getPendingSources(shortName, callback) {
var sources = [];
var count = 0;
db.get().collection('pending_sources', function(err, collection) {
collection.find({
'shortName': shortName
}).count(function(err, total) {
var cursor = collection.find({
'shortName': shortName
});
cursor.each(function(err, item) {
if (item != null) {
var sourceColl = db.collection('source_names');
sourceColl.find({
'sourceId': item.sourceId,
'shortName': shortName
}).toArray(function(err, existingSources) {
var source = {
objectId: item._id.toHexString(),
sourceId: item.sourceId,
name: item.name,
codeName: item.codeName,
callId: item.callId,
time: item.time,
existingSources: existingSources
};
sources.push(source);
count++;
if (count == total) {
callback(sources);
}
});
}
});
});
});
};
function insertPendingSource(shortName, sourceItem, res) {
db.get().collection('pending_sources', function(err, sourceNameCollection) {
sourceNameCollection.insert(sourceItem, function(err, result) {
if (err) {
console.warn(err.message);
res.status(404);
res.send({
error: err
});
return;
}
getPendingSources(shortName, function(sources) {
console.log("sending: " + util.inspect(sources));
res.send(JSON.stringify({
sources: sources,
source: sourceItem,
result: result.result
}));
});
});
});
};
function updatePendingSource(shortName, sourceItem, filter, res) {
db.get().collection('pending_sources', function(err, sourceNameCollection) {
sourceNameCollection.updateOne(filter, sourceItem, {
upsert: true
}, function(err, result) {
if (err) {
console.warn(err.message);
res.status(404);
res.send({
error: err
});
return;
}
getPendingSources(shortName, function(sources) {
res.send(JSON.stringify({
sources: sources,
source: sourceItem,
result: result.result
}));
});
});
});
};
app.post('/:shortName/pending_sources', function(req, res) {
res.contentType('json');
res.setHeader('Access-Control-Allow-Origin', '*');
if (req.body) {
var sourceId = req.body.sourceId;
if (!isNaN(sourceId) && (sourceId > 0)) {
var filter = {};
var name = req.body.name;
var codeName = req.body.codeName;
var call = req.body.call;
var time = new Date();
if (name) {
name = name.replace(/[^\w\s]/gi, '');
}
if (codeName) {
codeName = codeName.replace(/[^\w]/gi, '');
}
var sourceItem = {
sourceId: sourceId,
name: name,
codeName: codeName,
time: time
};
if (call) {
sourceItem.call = new BSON.ObjectID(call);
}
if (name && codeName) {
if (req.body.objectId) {
filter._id = ObjectID.createFromHexString(req.body.objectId);
updatePendingSource(req.params.shortName.toLowerCase(), sourceItem, filter, res);
} else {
insertPendingSource(req.params.shortName.toLowerCase(), sourceItem, res);
}
}
}
}
});

View File

@@ -0,0 +1,95 @@
var db = require('../db');
var schedule = require('node-schedule');
var sysStats = require("../sys_stats");
exports.init_stats = function() {
sysStats.initStats();
}
exports.get_errors = function(req, res) {
var short_name = req.params.shortName.toLowerCase();
var start = new Date();
start.setHours(start.getHours() - 1);
var collection = db.get().collection("calls");
collection.aggregate([{
$match: {
time: {
$gte: start
},
shortName: short_name
}
},
{
"$unwind": "$freqList"
},
{
"$project": {
"freqList": 1,
"errorRatio": {
$cond: [{
$eq: ["$freqList.len", 0]
}, 0, {
"$multiply": [{
"$divide": ["$freqList.error", "$freqList.len"]
}, 100]
}]
},
"time": "$time"
}
},
{
"$group": {
"_id": "$freqList.freq",
"values": {
"$push": {
"time": "$time",
"errors": "$errorRatio",
"spikes": "$freqList.spikes"
}
}
}
},
{
$sort: {
_id: -1
}
}
], function(err, results) {
if (err) {
console.warn("Error with error stats: " + util.inspect(req.params) + " err: " + err);
res.status(500);
res.send("Error with error stats: " + util.inspect(req.params) + " err: " + err);
} else {
res.contentType('json');
res.send(JSON.stringify(results));
}
});
}
exports.get_stats = function(req, res) {
var short_name = req.params.shortName.toLowerCase();
var callHistory = sysStats.callHistory(short_name);
var tgHistory = sysStats.tgHistory(short_name);
var errorTotals = sysStats.errorTotals(short_name);
if (callHistory && tgHistory) {
res.contentType('json');
res.send(JSON.stringify({
callHistory: callHistory,
tgHistory: tgHistory,
errorTotals: errorTotals
}));
} else {
console.log("ShortName didn't exist for stats: " + util.inspect(req.params));
res.status(500);
res.send("ShortName didn't exist for stats");
}
}
var statSched = schedule.scheduleJob('*/15 * * * *', function() {
sysStats.shiftStats();
});

View File

@@ -0,0 +1,51 @@
var mongoose = require("mongoose");
var User = require("../models/user");
var System = require("../models/system");
exports.get_systems = function (req, res) {
System.find().populate('userId', "screenName").
exec(function (err, results) {
if (err) {
console.error("Error - get_systems: " + err.message);
res.json({
success: false,
message: err
});
return;
}
var systemList = [];
for (var result in results) {
var clientCount = 0;
if (req.systemClients.hasOwnProperty(results[result].shortName)) {
clientCount = req.systemClients[results[result].shortName];
}
var system = {
name: results[result].name,
shortName: results[result].shortName,
systemType: results[result].systemType,
county: results[result].count,
country: results[result].country,
city: results[result].city,
state: results[result].state,
active: results[result].active,
callAvg: results[result].callAvg,
description: results[result].description,
planType: results[result].planType,
clientCount: clientCount
}
if (results[result].showScreenName && results[result].userId) {
system.screenName = results[result].userId.screenName
} else {
system.screenName = null;
}
systemList.push(system);
}
res.contentType('json');
res.send(JSON.stringify({
success: true,
systems: systemList
}));
});
}

View File

@@ -0,0 +1,18 @@
var db = require('../db');
exports.get_talkgroups = function(req, res) {
db.get().collection('talkgroups', function(err, tg_coll) {
tg_coll.find({
'shortName': req.params.shortName.toLowerCase()
}).toArray(function(err, tg_results) {
var talkgroups = {};
for (var tg in tg_results) {
talkgroups[tg_results[tg].num] = tg_results[tg];
}
res.contentType('json');
res.send(JSON.stringify({
talkgroups: talkgroups
}));
});
});
}

View File

@@ -0,0 +1,277 @@
var db = require('../db');
var mkdirp = require('mkdirp');
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 Group = require("../models/group");
var Call = require("../models/call");
var secrets = require("../config/secrets");
var util = require("util")
var config = require('../config/config.json');
var media_server = process.env['MEDIA_SERVER'] != null ? process.env['MEDIA_SERVER'] : 'https://media.openmhz.com';
var s3_endpoint = process.env['S3_ENDPOINT'] != null ? process.env['S3_ENDPOINT'] : 's3.us-west-1.wasabisys.com';
var s3_profile = process.env['S3_PROFILE'] != null ? process.env['S3_PROFILE'] : 'wasabi-account';
const wasabi = require('aws-sdk');
const wasabiEndpoint = new wasabi.Endpoint(s3_endpoint);
var wasabiCredentials = new wasabi.SharedIniFileCredentials({
profile: s3_profile
});
wasabi.config.credentials = wasabiCredentials;
const wasabiS3 = new wasabi.S3({
endpoint: wasabiEndpoint,
maxRetries: 0
});
async function callLength(file) {
return new Promise((resolve, reject) => {
probe(file, function(err, probeData) {
if (err) {
reject(err);
} else {
resolve(Math.round(probeData.format.duration));
}
});
})
}
exports.upload = function(req, res, next) {
process.nextTick(function() {
/** When using the "single"
data come in "req.file" regardless of the attribute "name". **/
var tmp_path = req.file.path;
/** The original name of the uploaded file
stored in the variable "originalname". **/
var target_path = 'uploads/' + req.file.originalname;
if (!req.file && (path.extname(req.file.originalname)) != '.m4a') {
console.warn("[" + req.params.shortName + "] Error file name is wrong or file does not exist");
res.status(500);
res.send("Error, invalid filename:\n");
return;
}
var shortName = req.params.shortName.toLowerCase();
var apiKey = req.body.api_key;
System.findOne({
'shortName': shortName
}, async function(err, item) {
if (err) {
console.warn("[" + req.params.shortName + "] Error /:shortName/upload - Error: " + err);
res.status(500);
res.send("Error, invalid shotName:\n" + err);
return;
}
if (item === null) {
console.warn("[" + req.params.shortName + "] Error /:shortName/upload ShortName does not exist");
res.status(500);
res.send("ShortName does not exist: " + shortName + "\n");
return;
}
if (apiKey != item.key) {
console.warn("[" + req.params.shortName + "] Error /:shortName/upload API Key Mismatch - Provided key: " + apiKey);
res.status(500);
res.send("API Keys do not match!\n");
return;
}
var talkgroupNum = parseInt(req.body.talkgroup_num);
var freq = parseFloat(req.body.freq);
var time = new Date(parseInt(req.body.start_time) * 1000);
var stopTime = new Date();
if (req.body.stop_time) {
var stopTime = new Date(parseInt(req.body.stop_time) * 1000);
}
var startTime = req.body.start_time;
var emergency = parseInt(req.body.emergency);
// Add in an API Key check
try {
var srcList = JSON.parse(req.body.source_list);
// Mongoose does not allow 'errors' to be used in the Schema for call. need to rename to error.
var badFreqList = JSON.parse(req.body.freq_list);
var freqList = badFreqList.map(obj =>{
obj.error = obj.errors;
delete obj.errors;
return obj;
});
} catch (err) {
var srcList = [];
var freqList = [];
console.warn("[" + req.params.shortName + "] Error /:shortName/upload Parsing Source/Freq List - Error: " + err);
res.status(500);
res.send("Error parsing sourcelist " + err);
}
var base_path = config.mediaDirectory;
var local_path = "/" + shortName + "/" + time.getFullYear() + "/" + (time.getMonth() + 1) + "/" + time.getDate() + "/";
var target_file = base_path + local_path + path.basename(req.file.originalname);
var object_key = "media/" + shortName + "-" + talkgroupNum + "-" + startTime + ".m4a";
//var endpoint = 'https://s3.amazonaws.com/openmhz/';
//var endpoint = 'https://s3.wasabisys.com/openmhz/';
var endpoint = s3_endpoint;
var bucket = 'openmhz'
//var url = 'https://openmhz.nyc3.cdn.digitaloceanspaces.com/' + object_key;
var url = endpoint + object_key;
//var url = 'https://s3.wasabisys.com/openmhz/' + object_key;
//var url = 'https://s3.amazonaws.com/openmhz/' + object_key;
var objectStore = true;
if (item.plan && (item.plan.type == "pro")) {
url = media_server + local_path + talkgroupNum + "-" + startTime + ".m4a";
objectStore = false;
}
var call = new Call({
shortName: shortName,
talkgroupNum: talkgroupNum,
objectKey: object_key,
endpoint: endpoint,
bucket: bucket,
time: time,
name: talkgroupNum + "-" + startTime + ".m4a",
freq: freq,
url: url,
emergency: emergency,
path: local_path,
srcList: srcList,
freqList: freqList,
len: -1
});
try {
if (req.body.call_length) {
call.len = parseInt(req.body.call_length);
} else {
call.len = (stopTime - time)/1000; //await callLength(req.file.path);
}
res.status(200).end();
if (!objectStore) {
mkdirp.sync(base_path + local_path, function(err) {
if (err) console.error(err);
});
var src = fs.createReadStream(req.file.path);
var dest = fs.createWriteStream(target_file);
dest.on('unpipe', (src) => {
src.end();
dest.end();
});
src.pipe(dest);
src.unpipe()
src.on('error', function(err) {
console.warn("[" + call.shortName + "] Error /:shortName/upload copying to location - Error: " + err + " Read: " + req.file.path + " Target: " + target_file);
fs.unlink(req.file.path, (err) => {
if (err)
console.log("[" + call.shortName + "] error deleting: " + req.file.path);
});
res.contentType('json');
res.send(JSON.stringify({
success: false,
error: "Upload failed"
}));
});
src.on('end', function() {
fs.unlink(req.file.path);
});
} else {
//var spacesSrc = fs.createReadStream(req.file.path);
//var awsSrc = fs.createReadStream(req.file.path);
var wasabiSrc = fs.createReadStream(req.file.path);
// call S3 to retrieve upload file to specified bucket
/* var spacesParams = {Bucket: 'openmhz', Key: object_key, Body: spacesSrc, ACL: 'public-read'};
// call S3 to retrieve upload file to specified bucket
spacesS3.upload (spacesParams, function (err, data) {
//fs.unlink(req.file.path);
if (err) {
console.log("Spaces Error", err);
}
});*/
/*
var awsParams = {Bucket: 'openmhz', Key: object_key, Body: awsSrc, ACL: 'public-read'};
awsS3.upload (awsParams, function (err, data) {
fs.unlink(req.file.path);
if (err) {
console.log("AWS Error", err);
}
});*/
var wasabiParams = {
Bucket: 'openmhz-west',
Key: object_key,
Body: wasabiSrc,
ACL: 'public-read'
};
var options = {partSize: 10 * 1024 * 1024, queueSize: 1};
/*var upload = new wasabiS3.ManagedUpload({
leavePartsOnError: true,
partSize: 10 * 1024 * 1024, queueSize: 1,
params: wasabiParams
});*/
wasabiS3.upload(wasabiParams, options, function(err, data) {
wasabiSrc.destroy();
fs.unlink(req.file.path, (err) => {
if (err) {
console.log("[" + call.shortName + "]error deleting: " + req.file.path);
}
call.save();
sysStats.addCall(call.toObject());
// we only want to notify clients if the clip is longer than 1 second.
if (call.len >= 1) {
req.call = call.toObject();
next();
}
});
if (err) {
console.log("[" + call.shortName + "] " + call.name + " - content-length: " + req.headers['content-length'] + " Wasabi Error", err);
}
});
}
} catch (err) {
console.warn("[" + call.shortName + "] Upload Error: " + err + " Filename: " + call.name + " content-length: " + req.headers['content-length']);
res.status(500);
sysStats.addError(call.toObject());
res.contentType('json');
res.send(JSON.stringify({
success: false,
error: "FFProbe"
}));
fs.unlink(req.file.path, (err) => {
if (err)
console.log("error deleting: " + req.file.path);
});
}
});
});
}