Prepare Build Testing

+ cleanup some comments functions
+ move some functions to startup.js
+ add ability to search videos with "startFrom" and "startTo" instead of "start" and "end"
merge-requests/35/head
Moe 2018-10-23 11:36:02 -07:00
parent e565b474a0
commit 224a06cb3e
10 changed files with 244 additions and 38 deletions

View File

@ -83,6 +83,6 @@ loadLib('ffmpeg')(s,config,function(){
loadLib('cloudUploaders')(s,config,lang) loadLib('cloudUploaders')(s,config,lang)
//notifiers : discord.. //notifiers : discord..
loadLib('notification')(s,config,lang) loadLib('notification')(s,config,lang)
//on-start actions //on-start actions, daemon(s) starter
loadLib('startup')(s,config,lang) loadLib('startup')(s,config,lang)
}) })

View File

@ -10,15 +10,15 @@ module.exports = function(s,config){
s.ffmpegKill=function(){ s.ffmpegKill=function(){
var cmd='' var cmd=''
if(s.isWin===true){ if(s.isWin===true){
cmd="Taskkill /IM ffmpeg.exe /F" cmd = "Taskkill /IM ffmpeg.exe /F"
}else{ }else{
cmd="ps aux | grep -ie ffmpeg | awk '{print $2}' | xargs kill -9" cmd = "ps aux | grep -ie ffmpeg | awk '{print $2}' | xargs kill -9"
} }
exec(cmd,{detached: true}) exec(cmd,{detached: true})
}; };
process.on('exit',s.ffmpegKill.bind(null,{cleanup:true})); process.on('exit',s.ffmpegKill.bind(null,{cleanup:true}));
process.on('SIGINT',s.ffmpegKill.bind(null, {exit:true})); process.on('SIGINT',s.ffmpegKill.bind(null, {exit:true}));
s.checkRelativePath=function(x){ s.checkRelativePath = function(x){
if(x.charAt(0)!=='/'){ if(x.charAt(0)!=='/'){
x=s.mainDirectory+'/'+x x=s.mainDirectory+'/'+x
} }

View File

@ -348,7 +348,7 @@ module.exports = function(s,config,lang){
var filename = s.formattedTime()+'.mp4' var filename = s.formattedTime()+'.mp4'
s.userLog(d,{type:"Traditional Recording",msg:"Started"}) s.userLog(d,{type:"Traditional Recording",msg:"Started"})
//-t 00:'+s.timeObject(new Date(detector_timeout * 1000 * 60)).format('mm:ss')+' //-t 00:'+s.timeObject(new Date(detector_timeout * 1000 * 60)).format('mm:ss')+'
s.group[d.ke].mon[d.id].eventBasedRecording.process = spawn(config.ffmpegDir,s.splitForFFPMEG(('-loglevel warning -analyzeduration 1000000 -probesize 1000000 -re -i http://'+config.ip+':'+config.port+'/'+d.auth+'/hls/'+d.ke+'/'+d.id+'/detectorStream.m3u8 -t 00:'+s.timeObject(new Date(detector_timeout * 1000 * 60)).format('mm:ss')+' -c:v copy -strftime 1 "'+s.getVideoDirectory(d.mon) + filename + '"').replace(/\s+/g,' ').trim())) s.group[d.ke].mon[d.id].eventBasedRecording.process = spawn(config.ffmpegDir,s.splitForFFPMEG(('-loglevel warning -analyzeduration 1000000 -probesize 1000000 -re -i http://'+config.ip+':'+config.port+'/'+d.auth+'/hls/'+d.ke+'/'+d.id+'/detectorStream.m3u8 -t 00:'+s.timeObject(new Date(detector_timeout * 1000 * 60)).format('mm:ss')+' -c:v copy -strftime 1 "'+s.getVideoDirectory(d.mon) + filename + '"')))
var ffmpegError=''; var ffmpegError='';
var error var error
s.group[d.ke].mon[d.id].eventBasedRecording.process.stderr.on('data',function(data){ s.group[d.ke].mon[d.id].eventBasedRecording.process.stderr.on('data',function(data){

View File

@ -110,7 +110,7 @@ module.exports = function(s,config,onFinish){
//ffmpeg string cleaner, splits for use with spawn() //ffmpeg string cleaner, splits for use with spawn()
s.splitForFFPMEG = function (ffmpegCommandAsString) { s.splitForFFPMEG = function (ffmpegCommandAsString) {
//this function ignores spaces inside quotes. //this function ignores spaces inside quotes.
return ffmpegCommandAsString.match(/\\?.|^$/g).reduce((p, c) => { return ffmpegCommandAsString.replace(/\s+/g,' ').trim().match(/\\?.|^$/g).reduce((p, c) => {
if(c === '"'){ if(c === '"'){
p.quote ^= 1; p.quote ^= 1;
}else if(!p.quote && c === ' '){ }else if(!p.quote && c === ' '){
@ -758,7 +758,7 @@ module.exports = function(s,config,onFinish){
x.pipe += ' -f singlejpeg '+x.detector_vf+x.cust_detect+x.dratio+' pipe:4'; x.pipe += ' -f singlejpeg '+x.detector_vf+x.cust_detect+x.dratio+' pipe:4';
} }
}else{ }else{
x.pipe+=' -f singlejpeg '+x.detector_vf+x.cust_detect+x.dratio+' pipe:3'; x.pipe+=' -f image2pipe '+x.detector_vf+x.cust_detect+x.dratio+' pipe:3';
} }
} }
//Traditional Recording Buffer //Traditional Recording Buffer
@ -885,8 +885,8 @@ module.exports = function(s,config,onFinish){
createPipeArray(e,x) createPipeArray(e,x)
//hold ffmpeg command for log stream //hold ffmpeg command for log stream
s.group[e.ke].mon[e.mid].ffmpeg = x.ffmpegCommandString s.group[e.ke].mon[e.mid].ffmpeg = x.ffmpegCommandString
//clean the string of spatial impurities //clean the string of spatial impurities and split for spawn()
x.ffmpegCommandString = s.splitForFFPMEG(x.ffmpegCommandString.replace(/\s+/g,' ').trim()) x.ffmpegCommandString = s.splitForFFPMEG(x.ffmpegCommandString)
//launch that bad boy //launch that bad boy
return spawn(config.ffmpegDir,x.ffmpegCommandString,{detached: true,stdio:x.stdioPipes}) return spawn(config.ffmpegDir,x.ffmpegCommandString,{detached: true,stdio:x.stdioPipes})
} }

View File

@ -1,12 +1,6 @@
var exec = require('child_process').exec; var exec = require('child_process').exec;
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
module.exports = function(s,config,lang,io){ module.exports = function(s,config,lang,io){
//check disk space every 20 minutes
if(config.autoDropCache===true){
setInterval(function(){
exec('echo 3 > /proc/sys/vm/drop_caches',{detached: true})
},60000*20);
}
s.sendDiskUsedAmountToClients = function(e){ s.sendDiskUsedAmountToClients = function(e){
//send the amount used disk space to connected users //send the amount used disk space to connected users
if(s.group[e.ke]&&s.group[e.ke].init){ if(s.group[e.ke]&&s.group[e.ke].init){
@ -48,7 +42,7 @@ module.exports = function(s,config,lang,io){
} }
callback(d) callback(d)
}); });
} else{ } else {
callback(0) callback(0)
} }
} }
@ -79,12 +73,4 @@ module.exports = function(s,config,lang,io){
callback(0) callback(0)
} }
} }
//master node - startup functions
setInterval(function(){
s.cpuUsage(function(cpu){
s.ramUsage(function(ram){
s.tx({f:'os',cpu:cpu,ram:ram},'CPU');
})
})
},10000);
} }

View File

@ -1,18 +1,16 @@
var knex = require('knex');
module.exports = function(s,config){ module.exports = function(s,config){
//sql/database connection with knex //sql/database connection with knex
var databaseOptions = { s.databaseOptions = {
client: config.databaseType, client: config.databaseType,
connection: config.db, connection: config.db,
} }
if(databaseOptions.client.indexOf('sqlite')>-1){ if(s.databaseOptions.client.indexOf('sqlite')>-1){
databaseOptions.client = 'sqlite3'; s.databaseOptions.client = 'sqlite3';
databaseOptions.useNullAsDefault = true; s.databaseOptions.useNullAsDefault = true;
} }
if(databaseOptions.client === 'sqlite3' && databaseOptions.connection.filename === undefined){ if(s.databaseOptions.client === 'sqlite3' && s.databaseOptions.connection.filename === undefined){
databaseOptions.connection.filename = s.mainDirectory+"/shinobi.sqlite" s.databaseOptions.connection.filename = s.mainDirectory+"/shinobi.sqlite"
} }
s.databaseEngine = knex(databaseOptions)
s.mergeQueryValues = function(query,values){ s.mergeQueryValues = function(query,values){
if(!values){values=[]} if(!values){values=[]}
var valuesNotFunction = true; var valuesNotFunction = true;
@ -60,7 +58,7 @@ module.exports = function(s,config){
console.log('s.sqlQuery ERROR',err) console.log('s.sqlQuery ERROR',err)
} }
if(onMoveOn && typeof onMoveOn === 'function'){ if(onMoveOn && typeof onMoveOn === 'function'){
switch(databaseOptions.client){ switch(s.databaseOptions.client){
case'sqlite3': case'sqlite3':
if(!r)r=[] if(!r)r=[]
break; break;

View File

@ -132,10 +132,30 @@ module.exports = function(s,config,lang,io){
} }
}) })
} }
//check disk space every 20 minutes
if(config.autoDropCache===true){
setInterval(function(){
exec('echo 3 > /proc/sys/vm/drop_caches',{detached: true})
},60000*20)
}
//master node - startup functions
setInterval(function(){
s.cpuUsage(function(cpu){
s.ramUsage(function(ram){
s.tx({f:'os',cpu:cpu,ram:ram},'CPU');
})
})
},10000)
//run prerequsite queries, load users and monitors
if(config.childNodes.mode !== 'child'){ if(config.childNodes.mode !== 'child'){
//sql/database connection with knex
s.databaseEngine = require('knex')(s.databaseOptions)
//run prerequsite queries
s.preQueries() s.preQueries()
setTimeout(function(){ setTimeout(function(){
//load administrators (groups)
loadAdminUsers(function(){ loadAdminUsers(function(){
//load monitors (for groups)
loadMonitors(function(){ loadMonitors(function(){
s.processReady() s.processReady()
}) })

103
libs/test.js Normal file
View File

@ -0,0 +1,103 @@
module.exports = function(s,config,lang,app,io){
var checkResult = function(functionName,expectedResult,testResult){
if(expectedResult !== testResult){
console.log(expectedResult,testResult)
throw new Error('- ' + functionName + ' : Failed!')
}else{
console.log('- ' + functionName + ' : Success')
}
}
var test = {
"basic.js" : {
checkRelativePath : function(){
var expectedResult = s.mainDirectory + '/'
var testResult = s.checkRelativePath('')
checkResult('checkRelativePath',expectedResult,testResult)
},
parseJSON : function(){
var expectedResult = {}
var testResult = s.parseJSON('{}')
checkResult('parseJSON',JSON.stringify(expectedResult),JSON.stringify(testResult))
},
stringJSON : function(){
var expectedResult = '{}'
var testResult = s.stringJSON({})
checkResult('stringJSON',expectedResult,testResult)
},
addUserPassToUrl : function(){
var expectedResult = 'http://user:pass@url.com'
var testResult = s.addUserPassToUrl('http://url.com','user','pass')
checkResult('addUserPassToUrl',expectedResult,testResult)
},
checkCorrectPathEnding : function(){
var expectedResult = '/'
var testResult = s.checkCorrectPathEnding('')
checkResult('checkCorrectPathEnding',expectedResult,testResult)
},
md5 : function(){
var expectedResult = '5f4dcc3b5aa765d61d8327deb882cf99'
var testResult = s.md5('password')
checkResult('md5',expectedResult,testResult)
},
sha256 : function(){
var expectedResult = '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
var testResult = require('crypto').createHash('sha256').update('test').digest("hex")
checkResult('createHash/sha256',expectedResult,testResult)
},
nameToTime : function(){
var expectedResult = '2018-10-22 23:00:00'
var testResult = s.nameToTime('2018-10-22T23-00-00.mp4')
checkResult('nameToTime',expectedResult,testResult)
},
ipRange : function(){
var expectedResult = [
'192.168.1.1',
'192.168.1.2',
'192.168.1.3'
]
var testResult = s.ipRange('192.168.1.1','192.168.1.3')
checkResult('ipRange',JSON.stringify(expectedResult),JSON.stringify(testResult))
},
portRange : function(){
var expectedResult = [
8000,
8001,
8002,
]
var testResult = s.portRange(8000,8002)
checkResult('portRange',JSON.stringify(expectedResult),JSON.stringify(testResult))
},
getFunctionParamNames : function(){
var testing = function(arg1,arg2){}
var expectedResult = [
'arg1',
'arg2',
]
var testResult = s.getFunctionParamNames(testing)
checkResult('getFunctionParamNames',JSON.stringify(expectedResult),JSON.stringify(testResult))
}
},
"ffmpeg.js" : {
splitForFFPMEG : function(){
var expectedResult = [
'flag1',
'flag2',
'flag3',
]
var testResult = s.splitForFFPMEG('flag1 flag2 "flag3"')
checkResult('splitForFFPMEG',JSON.stringify(expectedResult),JSON.stringify(testResult))
}
}
}
console.log('----- Function Test Starting')
Object.keys(test).forEach(function(libkey){
var library = test[libkey]
console.log('--- Testing ' + libkey + '...')
Object.keys(library).forEach(function(key){
var functionTest = library[key]
functionTest()
})
console.log('-- Completed ' + libkey + '...')
})
console.log('---- Function Test Ended')
}

View File

@ -973,10 +973,16 @@ module.exports = function(s,config,lang,app){
if(!req.query.endOperator||req.query.endOperator==''){ if(!req.query.endOperator||req.query.endOperator==''){
req.query.endOperator='<=' req.query.endOperator='<='
} }
var endIsStartTo
var theEndParameter = '`end`'
if(req.query.endIsStartTo){
endIsStartTo = true
theEndParameter = '`time`'
}
switch(true){ switch(true){
case(req.query.start&&req.query.start!==''&&req.query.end&&req.query.end!==''): case(req.query.start&&req.query.start!==''&&req.query.end&&req.query.end!==''):
req.sql+=' AND `time` '+req.query.startOperator+' ? AND `end` '+req.query.endOperator+' ?'; req.sql+=' AND `time` '+req.query.startOperator+' ? AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.count_sql+=' AND `time` '+req.query.startOperator+' ? AND `end` '+req.query.endOperator+' ?'; req.count_sql+=' AND `time` '+req.query.startOperator+' ? AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.ar.push(req.query.start) req.ar.push(req.query.start)
req.ar.push(req.query.end) req.ar.push(req.query.end)
req.count_ar.push(req.query.start) req.count_ar.push(req.query.start)
@ -989,8 +995,8 @@ module.exports = function(s,config,lang,app){
req.count_ar.push(req.query.start) req.count_ar.push(req.query.start)
break; break;
case(req.query.end&&req.query.end!==''): case(req.query.end&&req.query.end!==''):
req.sql+=' AND `end` '+req.query.endOperator+' ?'; req.sql+=' AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.count_sql+=' AND `end` '+req.query.endOperator+' ?'; req.count_sql+=' AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.ar.push(req.query.end) req.ar.push(req.query.end)
req.count_ar.push(req.query.end) req.count_ar.push(req.query.end)
break; break;
@ -1021,7 +1027,7 @@ module.exports = function(s,config,lang,app){
req.skip=0 req.skip=0
req.query.limit=parseInt(req.query.limit) req.query.limit=parseInt(req.query.limit)
} }
res.end(s.prettyPrint({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,videos:r})); res.end(s.prettyPrint({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,videos:r,endIsStartTo:endIsStartTo}));
}) })
}) })
},res,req); },res,req);

93
test.js Normal file
View File

@ -0,0 +1,93 @@
//
// Shinobi
// Copyright (C) 2016 Moe Alam, moeiscool
//
//
// # Donate
//
// If you like what I am doing here and want me to continue please consider donating :)
// PayPal : paypal@m03.ca
//
var os = require('os');
var io = new (require('socket.io'))()
// s = Shinobi
s = {
//Total Memory
coreCount : os.cpus().length,
//Total Memory
totalmem : os.totalmem(),
//Check Platform
platform : os.platform(),
//JSON stringify short-hand
s : JSON.stringify,
//Pretty Print JSON
prettyPrint : function(obj){return JSON.stringify(obj,null,3)},
//Check if Windows
isWin : (process.platform === 'win32' || process.platform === 'win64'),
//UTC Offset
utcOffset : require('moment')().utcOffset(),
//directory path for this file
mainDirectory : __dirname
}
//library loader
var loadLib = function(lib){
return require(__dirname+'/libs/'+lib+'.js')
}
//process handlers
loadLib('process')(process)
//configuration loader
var config = loadLib('config')(s)
// change ports for test
config.port = 9999
if(config.childNodes && config.childNodes.enabled === true && config.childNodes.mode === 'master'){
config.childNodes.port = 9998
}
//language loader
var lang = loadLib('language')(s,config)
//basic functions
loadLib('basic')(s,config)
//load extender functions
loadLib('extenders')(s,config)
//video processing engine
loadLib('ffmpeg')(s,config,function(){
//database connection : mysql, sqlite3..
loadLib('sql')(s,config)
//working directories : videos, streams, fileBin..
loadLib('folders')(s,config)
//authenticator functions : API, dashboard login..
loadLib('auth')(s,config,lang)
//express web server with ejs
var app = loadLib('webServer')(s,config,lang,io)
//web server routes : page handling..
loadLib('webServerPaths')(s,config,lang,app)
//web server routes for streams : streams..
loadLib('webServerStreamPaths')(s,config,lang,app)
//web server admin routes : create sub accounts, share monitors, share videos
loadLib('webServerAdminPaths')(s,config,lang,app)
//web server superuser routes : create admin accounts and manage system functions
loadLib('webServerSuperPaths')(s,config,lang,app)
//websocket connection handlers : login and streams..
loadLib('socketio')(s,config,lang,io)
//user and group functions
loadLib('user')(s,config)
//monitor/camera handlers
loadLib('monitor')(s,config,lang)
//event functions : motion, object matrix handler
loadLib('events')(s,config,lang)
//built-in detector functions : pam-diff..
loadLib('detector')(s,config)
//recording functions
loadLib('videos')(s,config,lang)
//plugins : websocket connected services..
loadLib('plugins')(s,config,lang)
//health : cpu and ram trackers..
loadLib('health')(s,config,lang,io)
//cluster module
loadLib('childNode')(s,config,lang,app,io)
//cloud uploaders : amazon s3, webdav, backblaze b2..
loadLib('cloudUploaders')(s,config,lang)
//notifiers : discord..
loadLib('notification')(s,config,lang)
//on-start actions, daemon(s) starter
loadLib('test')(s,config,lang,app,io)
})