2019-01-01 19:23:43 +00:00
var fs = require ( "fs" )
2018-09-28 05:37:08 +00:00
var Discord = require ( "discord.js" )
2020-07-12 22:37:14 +00:00
var template = require ( "./notifications/emailTemplate.js" )
2018-09-28 20:26:24 +00:00
module . exports = function ( s , config , lang ) {
2018-09-28 05:37:08 +00:00
//discord bot
if ( config . discordBot === true ) {
try {
s . discordMsg = function ( data , files , groupKey ) {
if ( ! data ) data = { } ;
var bot = s . group [ groupKey ] . discordBot
if ( ! bot ) {
2018-10-07 18:45:38 +00:00
s . userLog ( { ke : groupKey , mid : '$USER' } , { type : lang . DiscordFailedText , msg : lang . DiscordNotEnabledText } )
2018-09-28 05:37:08 +00:00
return
}
2020-08-13 00:37:04 +00:00
const sendBody = Object . assign ( {
2018-09-28 05:37:08 +00:00
color : 3447003 ,
title : 'Alert from Shinobi' ,
description : "" ,
fields : [ ] ,
timestamp : new Date ( ) ,
footer : {
icon _url : config . iconURL ,
text : "Shinobi Systems"
}
} , data )
2020-08-13 01:21:38 +00:00
const discordChannel = bot . channels . cache . get ( s . group [ groupKey ] . init . discordbot _channel )
2018-12-12 23:54:50 +00:00
if ( discordChannel && discordChannel . send ) {
discordChannel . send ( {
embed : sendBody ,
files : files
} ) . catch ( err => {
if ( err ) {
s . userLog ( { ke : groupKey , mid : '$USER' } , { type : lang . DiscordErrorText , msg : err } )
s . group [ groupKey ] . discordBot = null
s . loadGroupApps ( { ke : groupKey } )
}
} )
} else {
s . userLog ( {
ke : groupKey ,
mid : '$USER'
} , {
type : lang . DiscordErrorText ,
msg : 'Check the Channel ID'
} )
}
2018-09-28 05:37:08 +00:00
}
2020-08-13 00:37:04 +00:00
const onEventTriggerBeforeFilterForDiscord = function ( d , filter ) {
2018-10-01 05:44:35 +00:00
filter . discord = true
}
2020-08-13 00:37:04 +00:00
const onEventTriggerForDiscord = async ( d , filter ) => {
2018-10-01 05:44:35 +00:00
// d = event object
//discord bot
2019-07-26 16:13:33 +00:00
if ( filter . discord && s . group [ d . ke ] . discordBot && d . mon . details . detector _discordbot === '1' && ! s . group [ d . ke ] . activeMonitors [ d . id ] . detector _discordbot ) {
2018-10-01 05:44:35 +00:00
var detector _discordbot _timeout
if ( ! d . mon . details . detector _discordbot _timeout || d . mon . details . detector _discordbot _timeout === '' ) {
detector _discordbot _timeout = 1000 * 60 * 10 ;
} else {
detector _discordbot _timeout = parseFloat ( d . mon . details . detector _discordbot _timeout ) * 1000 * 60 ;
}
//lock mailer so you don't get emailed on EVERY trigger event.
2019-07-26 05:43:34 +00:00
s . group [ d . ke ] . activeMonitors [ d . id ] . detector _discordbot = setTimeout ( function ( ) {
2019-07-08 03:39:41 +00:00
clearTimeout ( s . group [ d . ke ] . activeMonitors [ d . id ] . detector _discordbot ) ;
delete ( s . group [ d . ke ] . activeMonitors [ d . id ] . detector _discordbot ) ;
2019-07-26 05:43:34 +00:00
} , detector _discordbot _timeout )
2018-10-01 05:44:35 +00:00
if ( d . mon . details . detector _discordbot _send _video === '1' ) {
2020-08-13 00:37:04 +00:00
// change to function that captures on going video capture, waits, grabs new video file, slices portion (max for transmission) and prepares for delivery
2018-10-01 05:44:35 +00:00
s . mergeDetectorBufferChunks ( d , function ( mergedFilepath , filename ) {
s . discordMsg ( {
author : {
2019-07-08 03:39:41 +00:00
name : s . group [ d . ke ] . rawMonitorConfigurations [ d . id ] . name ,
2018-10-01 05:44:35 +00:00
icon _url : config . iconURL
} ,
title : filename ,
fields : [ ] ,
timestamp : d . currentTime ,
footer : {
icon _url : config . iconURL ,
text : "Shinobi Systems"
}
} , [
{
attachment : mergedFilepath ,
name : filename
}
] , d . ke )
} )
}
2020-08-13 00:37:04 +00:00
const { screenShot , isStaticFile } = await s . getRawSnapshotFromMonitor ( d . mon , {
2019-10-03 02:17:20 +00:00
secondsInward : d . mon . details . snap _seconds _inward
2018-10-01 05:44:35 +00:00
} )
2020-08-13 00:37:04 +00:00
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 ,
2020-08-13 01:21:38 +00:00
fields : [ ] ,
2020-08-13 00:37:04 +00:00
timestamp : d . currentTime ,
footer : {
icon _url : config . iconURL ,
text : "Shinobi Systems"
}
2020-08-13 01:21:38 +00:00
} , [
{
attachment : screenShot ,
name : d . screenshotName + '.jpg'
}
] , d . ke )
2020-08-13 00:37:04 +00:00
}
2018-10-01 05:44:35 +00:00
}
}
2020-08-13 00:37:04 +00:00
const onTwoFactorAuthCodeNotificationForDiscord = function ( r ) {
2018-10-01 05:44:35 +00:00
// r = user
if ( r . details . factor _discord === '1' ) {
s . discordMsg ( {
author : {
name : r . lang [ '2-Factor Authentication' ] ,
icon _url : config . iconURL
} ,
title : r . lang [ 'Enter this code to proceed' ] ,
description : '**' + s . factorAuth [ r . ke ] [ r . uid ] . key + '** ' + r . lang . FactorAuthText1 ,
fields : [ ] ,
timestamp : new Date ( ) ,
footer : {
icon _url : config . iconURL ,
text : "Shinobi Systems"
}
} , [ ] , r . ke )
}
}
2020-08-13 00:37:04 +00:00
const loadDiscordBotForUser = function ( user ) {
const userDetails = s . parseJSON ( user . details ) ;
2018-09-30 22:44:04 +00:00
//discordbot
if ( ! s . group [ user . ke ] . discordBot &&
config . discordBot === true &&
2020-08-13 00:37:04 +00:00
userDetails . discordbot === '1' &&
userDetails . discordbot _token !== ''
2018-09-30 22:44:04 +00:00
) {
s . group [ user . ke ] . discordBot = new Discord . Client ( )
s . group [ user . ke ] . discordBot . on ( 'ready' , ( ) => {
2018-12-13 19:56:05 +00:00
s . userLog ( {
ke : user . ke ,
mid : '$USER'
} , {
type : lang . DiscordLoggedIn ,
msg : s . group [ user . ke ] . discordBot . user . tag
} )
2018-09-30 22:44:04 +00:00
} )
2020-08-13 00:37:04 +00:00
s . group [ user . ke ] . discordBot . login ( userDetails . discordbot _token )
2018-09-30 22:44:04 +00:00
}
}
2020-08-13 00:37:04 +00:00
const unloadDiscordBotForUser = function ( user ) {
2018-09-30 22:44:04 +00:00
if ( s . group [ user . ke ] . discordBot && s . group [ user . ke ] . discordBot . destroy ) {
s . group [ user . ke ] . discordBot . destroy ( )
delete ( s . group [ user . ke ] . discordBot )
}
}
2020-08-13 00:37:04 +00:00
const onDetectorNoTriggerTimeoutForDiscord = function ( e ) {
2019-11-01 00:26:52 +00:00
//e = monitor object
var currentTime = new Date ( )
if ( e . details . detector _notrigger _discord === '1' ) {
var html = '*' + lang . NoMotionEmailText2 + ' ' + ( e . details . detector _notrigger _timeout || 10 ) + ' ' + lang . minutes + '.*\n'
html += '**' + lang [ 'Monitor Name' ] + '** : ' + e . name + '\n'
html += '**' + lang [ 'Monitor ID' ] + '** : ' + e . id + '\n'
html += currentTime
s . discordMsg ( {
author : {
name : s . group [ e . ke ] . rawMonitorConfigurations [ e . id ] . name ,
icon _url : config . iconURL
} ,
title : lang [ '\"No Motion"\ Detector' ] ,
description : html ,
fields : [ ] ,
timestamp : currentTime ,
footer : {
icon _url : config . iconURL ,
text : "Shinobi Systems"
}
} , [ ] , e . ke )
}
}
2018-09-30 22:44:04 +00:00
s . loadGroupAppExtender ( loadDiscordBotForUser )
s . unloadGroupAppExtender ( unloadDiscordBotForUser )
2018-10-01 05:44:35 +00:00
s . onTwoFactorAuthCodeNotification ( onTwoFactorAuthCodeNotificationForDiscord )
s . onEventTrigger ( onEventTriggerForDiscord )
s . onEventTriggerBeforeFilter ( onEventTriggerBeforeFilterForDiscord )
2019-11-01 00:26:52 +00:00
s . onDetectorNoTriggerTimeout ( onDetectorNoTriggerTimeoutForDiscord )
2018-09-28 05:37:08 +00:00
} catch ( err ) {
2018-10-01 05:44:35 +00:00
console . log ( err )
2018-09-28 05:37:08 +00:00
console . log ( 'Could not start Discord bot, please run "npm install discord.js" inside the Shinobi folder.' )
s . discordMsg = function ( ) { }
}
}
2018-10-01 05:44:35 +00:00
// mailing with nodemailer
try {
if ( config . mail ) {
if ( config . mail . from === undefined ) { config . mail . from = '"ShinobiCCTV" <no-reply@shinobi.video>' }
s . nodemailer = require ( 'nodemailer' ) . createTransport ( config . mail ) ;
}
2020-08-13 00:37:04 +00:00
const onDetectorNoTriggerTimeoutForEmail = function ( e ) {
2018-10-01 05:44:35 +00:00
//e = monitor object
if ( config . mail && e . details . detector _notrigger _mail === '1' ) {
2020-07-10 05:48:34 +00:00
s . knexQuery ( {
action : "select" ,
columns : "mail" ,
table : "Users" ,
where : [
[ 'ke' , '=' , e . ke ] ,
[ 'details' , 'NOT LIKE' , '%"sub"%' ] ,
]
2020-07-11 20:16:01 +00:00
} , ( err , r ) => {
2018-10-01 05:44:35 +00:00
r = r [ 0 ]
var mailOptions = {
from : config . mail . from , // sender address
to : r . mail , // list of receivers
subject : lang . NoMotionEmailText1 + ' ' + e . name + ' (' + e . id + ')' , // Subject line
2019-11-01 00:26:52 +00:00
html : '<i>' + lang . NoMotionEmailText2 + ' ' + ( e . details . detector _notrigger _timeout || 10 ) + ' ' + lang . minutes + '.</i>' ,
2018-10-01 05:44:35 +00:00
}
mailOptions . html += '<div><b>' + lang [ 'Monitor Name' ] + ' </b> : ' + e . name + '</div>'
mailOptions . html += '<div><b>' + lang [ 'Monitor ID' ] + ' </b> : ' + e . id + '</div>'
s . nodemailer . sendMail ( mailOptions , ( error , info ) => {
if ( error ) {
2019-11-01 04:39:59 +00:00
s . systemLog ( 'detector:notrigger:sendMail' , error )
2018-10-01 05:44:35 +00:00
s . tx ( { f : 'error' , ff : 'detector_notrigger_mail' , id : e . id , ke : e . ke , error : error } , 'GRP_' + e . ke ) ;
return ;
}
s . tx ( { f : 'detector_notrigger_mail' , id : e . id , ke : e . ke , info : info } , 'GRP_' + e . ke ) ;
} )
} )
}
}
2020-08-13 00:37:04 +00:00
const onTwoFactorAuthCodeNotificationForEmail = function ( r ) {
2018-10-16 02:40:12 +00:00
// r = user object
2018-10-01 05:44:35 +00:00
if ( r . details . factor _mail !== '0' ) {
2020-08-13 00:37:04 +00:00
s . nodemailer . sendMail ( {
2018-10-01 05:44:35 +00:00
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 ,
2020-08-13 00:49:19 +00:00
} , ( error , info ) => {
2018-10-01 05:44:35 +00:00
if ( error ) {
s . systemLog ( r . lang . MailError , error )
return
}
} )
}
}
2020-08-13 00:37:04 +00:00
const onFilterEventForEmail = function ( x , d ) {
2018-10-01 05:44:35 +00:00
// x = filter function
// d = filter event object
if ( x === 'email' ) {
if ( d . videos && d . videos . length > 0 ) {
d . mailOptions = {
from : config . mail . from , // sender address
to : d . mail , // list of receivers
subject : lang [ 'Filter Matches' ] + ' : ' + d . name , // Subject line
html : lang . FilterMatchesText1 + ' ' + d . videos . length + ' ' + lang . FilterMatchesText2 ,
} ;
if ( d . execute && d . execute !== '' ) {
d . mailOptions . html += '<div><b>' + lang . Executed + ' :</b> ' + d . execute + '</div>'
}
if ( d . delete === '1' ) {
d . mailOptions . html += '<div><b>' + lang . Deleted + ' :</b> ' + lang . Yes + '</div>'
}
d . mailOptions . html += '<div><b>' + lang . Query + ' :</b> ' + d . query + '</div>'
d . mailOptions . html += '<div><b>' + lang [ 'Filter ID' ] + ' :</b> ' + d . id + '</div>'
s . nodemailer . sendMail ( d . mailOptions , ( error , info ) => {
if ( error ) {
s . tx ( { f : 'error' , ff : 'filter_mail' , ke : d . ke , error : error } , 'GRP_' + d . ke ) ;
return ;
}
s . tx ( { f : 'filter_mail' , ke : d . ke , info : info } , 'GRP_' + d . ke ) ;
} )
}
}
}
2020-08-13 00:37:04 +00:00
const onEventTriggerBeforeFilterForEmail = function ( d , filter ) {
2020-07-04 19:31:05 +00:00
if ( d . mon . details . detector _mail === '1' ) {
filter . mail = true
} else {
filter . mail = false
}
2018-10-01 05:44:35 +00:00
}
2020-08-13 00:37:04 +00:00
const onEventTriggerForEmail = async ( d , filter ) => {
2020-07-04 19:31:05 +00:00
if ( filter . mail && config . mail && ! s . group [ d . ke ] . activeMonitors [ d . id ] . detector _mail ) {
2020-07-10 05:48:34 +00:00
s . knexQuery ( {
action : "select" ,
columns : "mail" ,
table : "Users" ,
where : [
[ 'ke' , '=' , d . ke ] ,
[ 'details' , 'NOT LIKE' , '%"sub"%' ] ,
]
2020-08-13 00:37:04 +00:00
} , async ( err , r ) => {
r = r [ 0 ] ;
2018-10-01 05:44:35 +00:00
var detector _mail _timeout
if ( ! d . mon . details . detector _mail _timeout || d . mon . details . detector _mail _timeout === '' ) {
detector _mail _timeout = 1000 * 60 * 10 ;
} else {
detector _mail _timeout = parseFloat ( d . mon . details . detector _mail _timeout ) * 1000 * 60 ;
}
//lock mailer so you don't get emailed on EVERY trigger event.
2020-07-23 04:21:34 +00:00
s . group [ d . ke ] . activeMonitors [ d . id ] . detector _mail = setTimeout ( function ( ) {
2018-10-01 05:44:35 +00:00
//unlock so you can mail again.
2019-07-08 03:39:41 +00:00
clearTimeout ( s . group [ d . ke ] . activeMonitors [ d . id ] . detector _mail ) ;
delete ( s . group [ d . ke ] . activeMonitors [ d . id ] . detector _mail ) ;
2018-10-01 05:44:35 +00:00
} , detector _mail _timeout ) ;
2020-08-13 00:37:04 +00:00
const sendMail = function ( files ) {
2020-07-12 22:37:14 +00:00
const infoRows = [ ]
Object . keys ( d . details ) . forEach ( function ( key ) {
var value = d . details [ key ]
var text = value
if ( value instanceof Object ) {
text = JSON . stringify ( value , null , 3 )
}
infoRows . push ( template . createRow ( {
title : key ,
text : text
} ) )
2018-10-01 05:44:35 +00:00
} )
2020-07-12 22:37:14 +00:00
s . nodemailer . sendMail ( {
from : config . mail . from ,
to : r . mail ,
subject : lang . Event + ' - ' + d . screenshotName ,
html : template . createFramework ( {
title : lang . EventText1 + ' ' + d . currentTimestamp ,
subtitle : 'Shinobi Event' ,
body : infoRows . join ( '' ) ,
} ) ,
2020-08-13 00:37:04 +00:00
attachments : files || [ ]
2020-07-12 22:37:14 +00:00
} , ( error , info ) => {
2018-10-01 05:44:35 +00:00
if ( error ) {
s . systemLog ( lang . MailError , error )
return false ;
}
} )
}
if ( d . mon . details . detector _mail _send _video === '1' ) {
2020-08-13 00:37:04 +00:00
// change to function that captures on going video capture, waits, grabs new video file, slices portion (max for transmission) and prepares for delivery
2018-10-01 05:44:35 +00:00
s . mergeDetectorBufferChunks ( d , function ( mergedFilepath , filename ) {
2019-09-08 06:17:57 +00:00
fs . readFile ( mergedFilepath , function ( err , buffer ) {
if ( buffer ) {
s . nodemailer . sendMail ( {
from : config . mail . from ,
to : r . mail ,
subject : filename ,
html : '' ,
attachments : [
{
filename : filename ,
content : buffer
}
]
} , ( error , info ) => {
if ( error ) {
s . systemLog ( lang . MailError , error )
return false ;
}
} )
2018-10-01 05:44:35 +00:00
}
} )
} )
}
2020-08-13 00:37:04 +00:00
if ( ! d . screenshotBuffer ) {
const { screenShot , isStaticFile } = await s . getRawSnapshotFromMonitor ( d . mon , {
2019-10-03 02:17:20 +00:00
secondsInward : d . mon . details . snap _seconds _inward
2018-10-01 05:44:35 +00:00
} )
2020-08-13 00:37:04 +00:00
d . screenshotBuffer = screenShot
2018-10-01 05:44:35 +00:00
}
2020-08-13 00:37:04 +00:00
sendMail ( [
{
filename : d . screenshotName + '.jpg' ,
content : d . screenshotBuffer
}
] )
2018-10-01 05:44:35 +00:00
} )
}
}
s . onTwoFactorAuthCodeNotification ( onTwoFactorAuthCodeNotificationForEmail )
s . onEventTriggerBeforeFilter ( onEventTriggerBeforeFilterForEmail )
s . onEventTrigger ( onEventTriggerForEmail )
s . onFilterEvent ( onFilterEventForEmail )
s . onDetectorNoTriggerTimeout ( onDetectorNoTriggerTimeoutForEmail )
} catch ( err ) {
console . log ( err )
}
2018-09-28 05:37:08 +00:00
}