make s.getRawSnapshotFromMonitor a Promise function

install-with-shinobicctv-user-instead-of-root
Moe 2020-08-12 17:37:04 -07:00
parent a6fdc9cf51
commit f2828dd0cc
2 changed files with 203 additions and 209 deletions

View File

@ -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)
}

View File

@ -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" <no-reply@shinobi.video>'}
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']+' <b>'+s.factorAuth[r.ke][r.uid].key+'</b>. '+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()
})
}
}
])
})
}
}