From f2828dd0cc3062942e647ebdf7258840edf19e17 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 12 Aug 2020 17:37:04 -0700 Subject: [PATCH] make s.getRawSnapshotFromMonitor a Promise function --- libs/monitor.js | 287 ++++++++++++++++++++++--------------------- libs/notification.js | 125 +++++++++---------- 2 files changed, 203 insertions(+), 209 deletions(-) diff --git a/libs/monitor.js b/libs/monitor.js index 1f302161..af8547a2 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -107,141 +107,149 @@ module.exports = function(s,config,lang){ s.getStreamsDirectory = (monitor) => { return s.dir.streams + monitor.ke + '/' + monitor.mid + '/' } - s.getRawSnapshotFromMonitor = function(monitor,options,callback){ - if(!callback){ - callback = options + s.getRawSnapshotFromMonitor = function(monitor,options){ + return new Promise((resolve,reject) => { var options = {flags: ''} - } - s.checkDetails(monitor) - var inputOptions = [] - var outputOptions = [] - var streamDir = s.dir.streams + monitor.ke + '/' + monitor.mid + '/' - var url = options.url - var secondsInward = options.secondsInward || '0' - if(secondsInward.length === 1)secondsInward = '0' + secondsInward - if(options.flags)outputOptions.push(options.flags) - const checkExists = function(streamDir,callback){ - s.fileStats(streamDir,function(err){ - var response = false - if(err){ - // s.debugLog(err) - }else{ - response = true - } - callback(response) - }) - } - const noIconChecks = function(){ - const runExtraction = function(){ - var sendTempImage = function(){ - fs.readFile(temporaryImageFile,function(err,buffer){ - if(!err){ - callback(buffer,false) - } - fs.unlink(temporaryImageFile,function(){}) - }) - } - try{ - var snapBuffer = [] - var temporaryImageFile = streamDir + s.gid(5) + '.jpg' - var iconImageFile = streamDir + 'icon.jpg' - var ffmpegCmd = s.splitForFFPMEG(`-loglevel warning -re -probesize 100000 -analyzeduration 100000 ${inputOptions.join(' ')} -i "${url}" ${outputOptions.join(' ')} -f image2 -an -vf "fps=1" -vframes 1 "${temporaryImageFile}"`) - fs.writeFileSync(s.group[monitor.ke].activeMonitors[monitor.id].sdir + 'snapCmd.txt',JSON.stringify({ - cmd: ffmpegCmd, - temporaryImageFile: temporaryImageFile, - iconImageFile: iconImageFile, - useIcon: options.useIcon, - rawMonitorConfig: s.group[monitor.ke].rawMonitorConfigurations[monitor.mid], - },null,3),'utf8') - var cameraCommandParams = [ - s.mainDirectory + '/libs/cameraThread/snapshot.js', - config.ffmpegDir, - s.group[monitor.ke].activeMonitors[monitor.id].sdir + 'snapCmd.txt' - ] - var snapProcess = spawn('node',cameraCommandParams,{detached: true}) - snapProcess.stderr.on('data',function(data){ - console.log(data.toString()) - }) - snapProcess.on('close',function(data){ - clearTimeout(snapProcessTimeout) - sendTempImage() - }) - var snapProcessTimeout = setTimeout(function(){ - var pid = snapProcess.pid - if(s.isWin){ - spawn("taskkill", ["/pid", pid, '/t']) - }else{ - process.kill(-pid, 'SIGTERM') - } - setTimeout(function(){ - if(s.isWin === false){ - treekill(pid) + s.checkDetails(monitor) + var inputOptions = [] + var outputOptions = [] + var streamDir = s.dir.streams + monitor.ke + '/' + monitor.mid + '/' + var url = options.url + var secondsInward = options.secondsInward || '0' + if(secondsInward.length === 1)secondsInward = '0' + secondsInward + if(options.flags)outputOptions.push(options.flags) + const checkExists = function(streamDir,callback){ + s.fileStats(streamDir,function(err){ + var response = false + if(err){ + // s.debugLog(err) + }else{ + response = true + } + callback(response) + }) + } + const noIconChecks = function(){ + const runExtraction = function(){ + var sendTempImage = function(){ + fs.readFile(temporaryImageFile,function(err,buffer){ + if(!err){ + resolve({ + screenShot: buffer, + isStaticFile: false + }) + } + fs.unlink(temporaryImageFile,function(){}) + }) + } + try{ + var snapBuffer = [] + var temporaryImageFile = streamDir + s.gid(5) + '.jpg' + var iconImageFile = streamDir + 'icon.jpg' + var ffmpegCmd = s.splitForFFPMEG(`-loglevel warning -re -probesize 100000 -analyzeduration 100000 ${inputOptions.join(' ')} -i "${url}" ${outputOptions.join(' ')} -f image2 -an -vf "fps=1" -vframes 1 "${temporaryImageFile}"`) + fs.writeFileSync(s.group[monitor.ke].activeMonitors[monitor.id].sdir + 'snapCmd.txt',JSON.stringify({ + cmd: ffmpegCmd, + temporaryImageFile: temporaryImageFile, + iconImageFile: iconImageFile, + useIcon: options.useIcon, + rawMonitorConfig: s.group[monitor.ke].rawMonitorConfigurations[monitor.mid], + },null,3),'utf8') + var cameraCommandParams = [ + s.mainDirectory + '/libs/cameraThread/snapshot.js', + config.ffmpegDir, + s.group[monitor.ke].activeMonitors[monitor.id].sdir + 'snapCmd.txt' + ] + var snapProcess = spawn('node',cameraCommandParams,{detached: true}) + snapProcess.stderr.on('data',function(data){ + console.log(data.toString()) + }) + snapProcess.on('close',function(data){ + clearTimeout(snapProcessTimeout) + sendTempImage() + }) + var snapProcessTimeout = setTimeout(function(){ + var pid = snapProcess.pid + if(s.isWin){ + spawn("taskkill", ["/pid", pid, '/t']) }else{ - snapProcess.kill() + process.kill(-pid, 'SIGTERM') } - },10000) - },30000) - }catch(err){ - console.log(err) + setTimeout(function(){ + if(s.isWin === false){ + treekill(pid) + }else{ + snapProcess.kill() + } + },10000) + },30000) + }catch(err){ + console.log(err) + } + } + if(url){ + runExtraction() + }else{ + checkExists(streamDir + 's.jpg',function(success){ + if(success === false){ + checkExists(streamDir + 'detectorStream.m3u8',function(success){ + if(success === false){ + checkExists(streamDir + 's.m3u8',function(success){ + if(success === false){ + switch(monitor.type){ + case'h264': + switch(monitor.protocol){ + case'rtsp': + if( + monitor.details.rtsp_transport + && monitor.details.rtsp_transport !== '' + && monitor.details.rtsp_transport !== 'no' + ){ + inputOptions.push('-rtsp_transport ' + monitor.details.rtsp_transport) + } + break; + } + break; + } + url = s.buildMonitorUrl(monitor) + }else{ + outputOptions.push(`-ss 00:00:${secondsInward}`) + url = streamDir + 's.m3u8' + } + runExtraction() + }) + }else{ + outputOptions.push(`-ss 00:00:${secondsInward}`) + url = streamDir + 'detectorStream.m3u8' + runExtraction() + } + }) + }else{ + s.readFile(streamDir + 's.jpg',function(err,snapBuffer){ + resolve({ + screenShot: snapBuffer, + isStaticFile: true + }) + }) + } + }) } } - if(url){ - runExtraction() - }else{ - checkExists(streamDir + 's.jpg',function(success){ + if(options.useIcon === true){ + checkExists(streamDir + 'icon.jpg',function(success){ if(success === false){ - checkExists(streamDir + 'detectorStream.m3u8',function(success){ - if(success === false){ - checkExists(streamDir + 's.m3u8',function(success){ - if(success === false){ - switch(monitor.type){ - case'h264': - switch(monitor.protocol){ - case'rtsp': - if( - monitor.details.rtsp_transport - && monitor.details.rtsp_transport !== '' - && monitor.details.rtsp_transport !== 'no' - ){ - inputOptions.push('-rtsp_transport ' + monitor.details.rtsp_transport) - } - break; - } - break; - } - url = s.buildMonitorUrl(monitor) - }else{ - outputOptions.push(`-ss 00:00:${secondsInward}`) - url = streamDir + 's.m3u8' - } - runExtraction() - }) - }else{ - outputOptions.push(`-ss 00:00:${secondsInward}`) - url = streamDir + 'detectorStream.m3u8' - runExtraction() - } - }) + noIconChecks() }else{ - s.readFile(streamDir + 's.jpg',function(err,snapBuffer){ - callback(snapBuffer,true) + var snapBuffer = fs.readFileSync(streamDir + 'icon.jpg') + resolve({ + screenShot: snapBuffer, + isStaticFile: false }) } }) + }else{ + noIconChecks() } - } - if(options.useIcon === true){ - checkExists(streamDir + 'icon.jpg',function(success){ - if(success === false){ - noIconChecks() - }else{ - var snapBuffer = fs.readFileSync(streamDir + 'icon.jpg') - callback(snapBuffer,false) - } - }) - }else{ - noIconChecks() - } + }) } s.mergeDetectorBufferChunks = function(monitor,callback){ var pathDir = s.dir.streams+monitor.ke+'/'+monitor.id+'/' @@ -513,28 +521,27 @@ module.exports = function(s,config,lang){ } return options } - s.cameraSendSnapshot = function(e,options){ + s.cameraSendSnapshot = async (e,options) => { if(!options)options = {} s.checkDetails(e) if(config.doSnapshot === true){ if(s.group[e.ke] && s.group[e.ke].rawMonitorConfigurations && s.group[e.ke].rawMonitorConfigurations[e.mid] && s.group[e.ke].rawMonitorConfigurations[e.mid].mode !== 'stop'){ var pathDir = s.dir.streams+e.ke+'/'+e.mid+'/' - s.getRawSnapshotFromMonitor(s.group[e.ke].rawMonitorConfigurations[e.mid],Object.assign({ + const {screenShot, isStaticFile} = await s.getRawSnapshotFromMonitor(s.group[e.ke].rawMonitorConfigurations[e.mid],Object.assign({ flags: '-s 200x200' - },options),function(data,isStaticFile){ - if(data && (data[data.length-2] === 0xFF && data[data.length-1] === 0xD9)){ - s.tx({ - f: 'monitor_snapshot', - snapshot: data.toString('base64'), - snapshot_format: 'b64', - mid: e.mid, - ke: e.ke - },'GRP_'+e.ke) - }else{ - console.log('not image') - s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke) - } - }) + },options)) + if(screenShot && (screenShot[screenShot.length-2] === 0xFF && screenShot[screenShot.length-1] === 0xD9)){ + s.tx({ + f: 'monitor_snapshot', + snapshot: screenShot.toString('base64'), + snapshot_format: 'b64', + mid: e.mid, + ke: e.ke + },'GRP_'+e.ke) + }else{ + console.log('not image') + s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke) + } }else{ s.tx({f:'monitor_snapshot',snapshot:'Disabled',snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke) } diff --git a/libs/notification.js b/libs/notification.js index 7f6db1a8..9b432d82 100644 --- a/libs/notification.js +++ b/libs/notification.js @@ -12,7 +12,7 @@ module.exports = function(s,config,lang){ s.userLog({ke:groupKey,mid:'$USER'},{type:lang.DiscordFailedText,msg:lang.DiscordNotEnabledText}) return } - var sendBody = Object.assign({ + const sendBody = Object.assign({ color: 3447003, title: 'Alert from Shinobi', description: "", @@ -23,7 +23,7 @@ module.exports = function(s,config,lang){ text: "Shinobi Systems" } },data) - var discordChannel = bot.channels.get(s.group[groupKey].init.discordbot_channel) + const discordChannel = bot.channels.get(s.group[groupKey].init.discordbot_channel) if(discordChannel && discordChannel.send){ discordChannel.send({ embed: sendBody, @@ -45,10 +45,10 @@ module.exports = function(s,config,lang){ }) } } - var onEventTriggerBeforeFilterForDiscord = function(d,filter){ + const onEventTriggerBeforeFilterForDiscord = function(d,filter){ filter.discord = true } - var onEventTriggerForDiscord = function(d,filter){ + const onEventTriggerForDiscord = async (d,filter) => { // d = event object //discord bot if(filter.discord && s.group[d.ke].discordBot && d.mon.details.detector_discordbot === '1' && !s.group[d.ke].activeMonitors[d.id].detector_discordbot){ @@ -60,28 +60,11 @@ module.exports = function(s,config,lang){ } //lock mailer so you don't get emailed on EVERY trigger event. s.group[d.ke].activeMonitors[d.id].detector_discordbot = setTimeout(function(){ - //unlock so you can mail again. clearTimeout(s.group[d.ke].activeMonitors[d.id].detector_discordbot); delete(s.group[d.ke].activeMonitors[d.id].detector_discordbot); },detector_discordbot_timeout) - var files = [] - var sendAlert = function(){ - s.discordMsg({ - author: { - name: s.group[d.ke].rawMonitorConfigurations[d.id].name, - icon_url: config.iconURL - }, - title: lang.Event+' - '+d.screenshotName, - description: lang.EventText1+' '+d.currentTimestamp, - fields: [], - timestamp: d.currentTime, - footer: { - icon_url: config.iconURL, - text: "Shinobi Systems" - } - },files,d.ke) - } if(d.mon.details.detector_discordbot_send_video === '1'){ + // change to function that captures on going video capture, waits, grabs new video file, slices portion (max for transmission) and prepares for delivery s.mergeDetectorBufferChunks(d,function(mergedFilepath,filename){ s.discordMsg({ author: { @@ -103,21 +86,32 @@ module.exports = function(s,config,lang){ ],d.ke) }) } - s.getRawSnapshotFromMonitor(d.mon,{ + const {screenShot, isStaticFile} = await s.getRawSnapshotFromMonitor(d.mon,{ secondsInward: d.mon.details.snap_seconds_inward - },function(data){ - if(data[data.length - 2] === 0xFF && data[data.length - 1] === 0xD9){ - d.screenshotBuffer = data - files.push({ - attachment: d.screenshotBuffer, - name: d.screenshotName+'.jpg' - }) - } - sendAlert() }) + if(screenShot[screenShot.length - 2] === 0xFF && screenShot[screenShot.length - 1] === 0xD9){ + d.screenshotBuffer = screenShot + s.discordMsg({ + author: { + name: s.group[d.ke].rawMonitorConfigurations[d.id].name, + icon_url: config.iconURL + }, + title: lang.Event+' - '+d.screenshotName, + description: lang.EventText1+' '+d.currentTimestamp, + fields: [{ + attachment: screenShot, + name: d.screenshotName+'.jpg' + }], + timestamp: d.currentTime, + footer: { + icon_url: config.iconURL, + text: "Shinobi Systems" + } + },files,d.ke) + } } } - var onTwoFactorAuthCodeNotificationForDiscord = function(r){ + const onTwoFactorAuthCodeNotificationForDiscord = function(r){ // r = user if(r.details.factor_discord === '1'){ s.discordMsg({ @@ -136,13 +130,13 @@ module.exports = function(s,config,lang){ },[],r.ke) } } - var loadDiscordBotForUser = function(user){ - ar=JSON.parse(user.details); + const loadDiscordBotForUser = function(user){ + const userDetails = s.parseJSON(user.details); //discordbot if(!s.group[user.ke].discordBot && config.discordBot === true && - ar.discordbot === '1' && - ar.discordbot_token !== '' + userDetails.discordbot === '1' && + userDetails.discordbot_token !== '' ){ s.group[user.ke].discordBot = new Discord.Client() s.group[user.ke].discordBot.on('ready', () => { @@ -154,16 +148,16 @@ module.exports = function(s,config,lang){ msg: s.group[user.ke].discordBot.user.tag }) }) - s.group[user.ke].discordBot.login(ar.discordbot_token) + s.group[user.ke].discordBot.login(userDetails.discordbot_token) } } - var unloadDiscordBotForUser = function(user){ + const unloadDiscordBotForUser = function(user){ if(s.group[user.ke].discordBot && s.group[user.ke].discordBot.destroy){ s.group[user.ke].discordBot.destroy() delete(s.group[user.ke].discordBot) } } - var onDetectorNoTriggerTimeoutForDiscord = function(e){ + const onDetectorNoTriggerTimeoutForDiscord = function(e){ //e = monitor object var currentTime = new Date() if(e.details.detector_notrigger_discord === '1'){ @@ -205,7 +199,7 @@ module.exports = function(s,config,lang){ if(config.mail.from === undefined){config.mail.from = '"ShinobiCCTV" '} s.nodemailer = require('nodemailer').createTransport(config.mail); } - var onDetectorNoTriggerTimeoutForEmail = function(e){ + const onDetectorNoTriggerTimeoutForEmail = function(e){ //e = monitor object if(config.mail && e.details.detector_notrigger_mail === '1'){ s.knexQuery({ @@ -237,16 +231,15 @@ module.exports = function(s,config,lang){ }) } } - var onTwoFactorAuthCodeNotificationForEmail = function(r){ + const onTwoFactorAuthCodeNotificationForEmail = function(r){ // r = user object if(r.details.factor_mail !== '0'){ - var mailOptions = { + s.nodemailer.sendMail({ from: config.mail.from, to: r.mail, subject: r.lang['2-Factor Authentication'], html: r.lang['Enter this code to proceed']+' '+s.factorAuth[r.ke][r.uid].key+'. '+r.lang.FactorAuthText1, - }; - s.nodemailer.sendMail(mailOptions, (error, info) => { + };, (error, info) => { if (error) { s.systemLog(r.lang.MailError,error) return @@ -254,7 +247,7 @@ module.exports = function(s,config,lang){ }) } } - var onFilterEventForEmail = function(x,d){ + const onFilterEventForEmail = function(x,d){ // x = filter function // d = filter event object if(x === 'email'){ @@ -283,14 +276,14 @@ module.exports = function(s,config,lang){ } } } - var onEventTriggerBeforeFilterForEmail = function(d,filter){ + const onEventTriggerBeforeFilterForEmail = function(d,filter){ if(d.mon.details.detector_mail === '1'){ filter.mail = true }else{ filter.mail = false } } - var onEventTriggerForEmail = function(d,filter){ + const onEventTriggerForEmail = async (d,filter) => { if(filter.mail && config.mail && !s.group[d.ke].activeMonitors[d.id].detector_mail){ s.knexQuery({ action: "select", @@ -300,8 +293,8 @@ module.exports = function(s,config,lang){ ['ke','=',d.ke], ['details','NOT LIKE','%"sub"%'], ] - },(err,r) => { - r=r[0]; + },async (err,r) => { + r = r[0]; var detector_mail_timeout if(!d.mon.details.detector_mail_timeout||d.mon.details.detector_mail_timeout===''){ detector_mail_timeout = 1000*60*10; @@ -314,8 +307,7 @@ module.exports = function(s,config,lang){ clearTimeout(s.group[d.ke].activeMonitors[d.id].detector_mail); delete(s.group[d.ke].activeMonitors[d.id].detector_mail); },detector_mail_timeout); - var files = [] - var sendMail = function(){ + const sendMail = function(files){ const infoRows = [] Object.keys(d.details).forEach(function(key){ var value = d.details[key] @@ -337,7 +329,7 @@ module.exports = function(s,config,lang){ subtitle: 'Shinobi Event', body: infoRows.join(''), }), - attachments: files + attachments: files || [] }, (error, info) => { if (error) { s.systemLog(lang.MailError,error) @@ -346,6 +338,7 @@ module.exports = function(s,config,lang){ }) } if(d.mon.details.detector_mail_send_video === '1'){ + // change to function that captures on going video capture, waits, grabs new video file, slices portion (max for transmission) and prepares for delivery s.mergeDetectorBufferChunks(d,function(mergedFilepath,filename){ fs.readFile(mergedFilepath,function(err,buffer){ if(buffer){ @@ -370,24 +363,18 @@ module.exports = function(s,config,lang){ }) }) } - if(d.screenshotBuffer){ - files.push({ + if(!d.screenshotBuffer){ + const {screenShot, isStaticFile} = await s.getRawSnapshotFromMonitor(d.mon,{ + secondsInward: d.mon.details.snap_seconds_inward + }) + d.screenshotBuffer = screenShot + } + sendMail([ + { filename: d.screenshotName + '.jpg', content: d.screenshotBuffer - }) - sendMail() - }else{ - s.getRawSnapshotFromMonitor(d.mon,{ - secondsInward: d.mon.details.snap_seconds_inward - },function(data){ - d.screenshotBuffer = data - files.push({ - filename: d.screenshotName + '.jpg', - content: data - }) - sendMail() - }) - } + } + ]) }) } }