const fs = require("fs") const fetch = require("node-fetch") module.exports = function(s,config,lang,getSnapshot){ const { getObjectTagNotifyText, getEventBasedRecordingUponCompletion, } = require('../events/utils.js')(s,config,lang) //matrix bot if(config.matrixBot === true){ const sdk = require("matrix-js-sdk") try{ function sendFile(file,groupKey){ const client = s.group[groupKey].matrixBot const roomId = s.group[groupKey].matrixBotRoom const { buffer, name, type, info, opttype, } = file; client.uploadContent(buffer, { name: name, type: opttype, }).then(function(url) { const content = { msgtype: type || "m.file", body: name, info: info, url: url.content_uri }; client.sendMessage(roomId, content); }).catch(err => { s.userLog({ ke: groupKey, mid: '$USER' },{ type: 'matrix.org Error', msg: err }); }) } const sendMessage = function(data,files,groupKey){ if(!data)data = {}; const client = s.group[groupKey].matrixBot const roomId = s.group[groupKey].matrixBotRoom if(!client){ s.userLog({ke:groupKey,mid:'$USER'},{type:'matrix.org Error'}) return } if(client.sendMessage){ if(data.text){ const sendBody = { "body": data.text, "msgtype": "m.text" } client.sendMessage(roomId, sendBody); } files.forEach((file) => { sendFile(file,groupKey) }); }else{ s.userLog({ ke: groupKey, mid: '$USER' },{ type: 'matrix.org Error', msg: '!sendMessage' }); } } const onEventTriggerBeforeFilterForMatrixBot = function(d,filter){ filter.matrixBot = false } const onEventTriggerForMatrixBot = async (d,filter) => { const monitorConfig = s.group[d.ke].rawMonitorConfigurations[d.id] // d = event object const isEnabled = filter.matrixBot || monitorConfig.details.detector_matrixbot === '1' || monitorConfig.details.notify_matrix === '1' if(s.group[d.ke].matrixBot && isEnabled && !s.group[d.ke].activeMonitors[d.id].detector_matrixbot){ const notifyText = getObjectTagNotifyText(d) var detector_matrixbot_timeout if(!monitorConfig.details.detector_matrixbot_timeout||monitorConfig.details.detector_matrixbot_timeout===''){ detector_matrixbot_timeout = 1000 * 60 * 10; }else{ detector_matrixbot_timeout = parseFloat(monitorConfig.details.detector_matrixbot_timeout) * 1000 * 60; } s.group[d.ke].activeMonitors[d.id].detector_matrixbot = setTimeout(function(){ clearTimeout(s.group[d.ke].activeMonitors[d.id].detector_matrixbot); s.group[d.ke].activeMonitors[d.id].detector_matrixbot = null },detector_matrixbot_timeout) await getSnapshot(d,monitorConfig) if(d.screenshotBuffer){ sendMessage({ text: notifyText, },[ { buffer: d.screenshotBuffer, name: d.screenshotName+'.jpg', type: 'm.image', opttype: 'image/jpeg', info: { mimetype: 'image/jpeg', }, } ],d.ke) } if(monitorConfig.details.detector_matrixbot_send_video === '1'){ let videoPath = null let videoName = null const eventBasedRecording = await getEventBasedRecordingUponCompletion({ ke: d.ke, mid: d.mid }) if(eventBasedRecording.filePath){ videoPath = eventBasedRecording.filePath videoName = eventBasedRecording.filename }else{ const siftedVideoFileFromRam = await s.mergeDetectorBufferChunks(d) videoPath = siftedVideoFileFromRam.filePath videoName = siftedVideoFileFromRam.filename } if(videoPath){ sendMessage({ text: notifyText, },[ { buffer: await fs.promises.readFile(videoPath), name: videoName, type: 'm.video', opttype: 'video/mp4', info: { mimetype: 'video/mp4', }, } ],d.ke) } } } } const onTwoFactorAuthCodeNotificationForMatrixBot = function(user){ // r = user if(r.details.factor_matrixbot === '1'){ const eventText = `${user.lang['2-Factor Authentication']} : ${user.lang['Enter this code to proceed']} **${factorAuthKey}** ${user.lang.FactorAuthText1}` sendMessage({ text: eventText, },[],d.ke) } } const loadMatrixBotForUser = function(user){ const userDetails = s.parseJSON(user.details); //matrixbot if(!s.group[user.ke].matrixBot && config.matrixBot === true && userDetails.matrixbot === '1' && userDetails.matrixbot_baseUrl && userDetails.matrixbot_accessToken && userDetails.matrixbot_userId && userDetails.matrixbot_roomId ){ s.debugLog(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`) s.debugLog(`Matrix Connecting... ${userDetails.matrixbot_baseUrl}`) const client = sdk.createClient({ baseUrl: userDetails.matrixbot_baseUrl, accessToken: userDetails.matrixbot_accessToken, userId: userDetails.matrixbot_userId }); s.group[user.ke].matrixBot = client s.group[user.ke].matrixBotRoom = userDetails.matrixbot_roomId client.startClient(); client.once('sync', function(state, prevState, res) { s.userLog({ ke: user.ke, mid: '$USER' },{ type: 'matrix.org', msg: lang.Ready }) }); } } const unloadMatrixBotForUser = function(user){ if(s.group[user.ke].matrixBot && s.group[user.ke].matrixBot.stopClient){ s.group[user.ke].matrixBot.stopClient() delete(s.group[user.ke].matrixBot) } } const onDetectorNoTriggerTimeoutForMatrixBot = function(e){ //e = monitor object var currentTime = new Date() if(e.details.detector_notrigger_matrixbot === '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 const eventText = `${lang['"No Motion" Detector']} : ${html}` sendMessage({ text: eventText, },[],e.ke) } } const onMonitorUnexpectedExitForMatrixBot = (monitorConfig) => { const isEnabled = monitorConfig.details.detector_matrixbot === '1' || monitorConfig.details.notify_matrix === '1' if(isEnabled && monitorConfig.details.notify_onUnexpectedExit === '1'){ const ffmpegCommand = s.group[monitorConfig.ke].activeMonitors[monitorConfig.mid].ffmpeg const description = lang['Process Crashed for Monitor'] + '\n' + ffmpegCommand const currentTime = new Date() const eventText = `${lang['Process Unexpected Exit']} : ${monitorConfig.name} : ${description}` sendMessage({ text: eventText, },[],monitorConfig.ke) } } s.loadGroupAppExtender(loadMatrixBotForUser) s.unloadGroupAppExtender(unloadMatrixBotForUser) s.onTwoFactorAuthCodeNotification(onTwoFactorAuthCodeNotificationForMatrixBot) s.onEventTrigger(onEventTriggerForMatrixBot) s.onEventTriggerBeforeFilter(onEventTriggerBeforeFilterForMatrixBot) s.onDetectorNoTriggerTimeout(onDetectorNoTriggerTimeoutForMatrixBot) s.onMonitorUnexpectedExit(onMonitorUnexpectedExitForMatrixBot) s.definitions["Monitor Settings"].blocks["Notifications"].info[0].info.push( { "name": "detail=notify_matrix", "field": "Matrix.org", "description": "", "default": "0", "example": "", "selector": "h_det_matrixbot", "fieldType": "select", "possible": [ { "name": lang.No, "value": "0" }, { "name": lang.Yes, "value": "1" } ] } ) s.definitions["Monitor Settings"].blocks["Notifications"].info.push({ "evaluation": "$user.details.use_matrixbot !== '0'", isFormGroupGroup: true, "name": "Matrix.org", "color": "purple", "section-class": "h_det_matrixbot_input h_det_matrixbot_1", "info": [ { "name": "detail=detector_matrixbot_send_video", "field": lang["Attach Video Clip"] + ` (${lang['on Event']})`, "description": "", "default": "0", "example": "", "fieldType": "select", "possible": [ { "name": lang.No, "value": "0" }, { "name": lang.Yes, "value": "1" } ] }, { "name": "detail=detector_matrixbot_timeout", "field": lang['Allow Next Alert'] + ` (${lang['on Event']})`, "description": "", "default": "10", "example": "", "possible": "" }, { "name": "detail=detector_notrigger_matrixbot", "field": lang['No Trigger'], "description": lang.noTriggerText, "default": "0", "example": "", "fieldType": "select", "possible": [ { "name": lang.No, "value": "0" }, { "name": lang.Yes, "value": "1" } ] }, ] }) s.definitions["Account Settings"].blocks["2-Factor Authentication"].info.push({ "name": "detail=factor_matrixbot", "field": 'Matrix.org', "default": "1", "example": "", "fieldType": "select", "possible": [ { "name": lang.No, "value": "0" }, { "name": lang.Yes, "value": "1" } ] }) s.definitions["Account Settings"].blocks["Matrix.org"] = { "evaluation": "$user.details.use_matrixbot !== '0'", "name": "Matrix.org", "color": "purple", "info": [ { "name": "detail=matrixbot", "selector":"u_matrixbot_bot", "field": lang.Enabled, "default": "0", "example": "", "fieldType": "select", "possible": [ { "name": lang.No, "value": "0" }, { "name": lang.Yes, "value": "1" } ] }, { hidden: true, "name": "detail=matrixbot_baseUrl", "placeholder": "", "field": lang["Host"], "form-group-class":"u_matrixbot_bot_input u_matrixbot_bot_1", }, { hidden: true, "name": "detail=matrixbot_userId", "placeholder": "xxxxxxxxxxxxxxxxxx", "field": lang["User ID"], "form-group-class":"u_matrixbot_bot_input u_matrixbot_bot_1", }, { hidden: true, "name": "detail=matrixbot_roomId", "placeholder": "xxxxxxxxxxxxxxxxxx", "field": lang["Room ID"], "form-group-class":"u_matrixbot_bot_input u_matrixbot_bot_1", }, { hidden: true, "name": "detail=matrixbot_accessToken", "fieldType": "password", "placeholder": "XXXXXXXXXXXXXXXXXXXXXXXX", "field": lang.Token, "form-group-class":"u_matrixbot_bot_input u_matrixbot_bot_1", }, ] } s.definitions["Event Filters"].blocks["Action for Selected"].info.push({ "name": "actions=matrixBot", "field": 'Matrix.org', "fieldType": "select", "form-group-class": "actions-row", "default": "", "example": "1", "possible": [ { "name": lang['Original Choice'], "value": "", "selected": true }, { "name": lang.Yes, "value": "1", } ] }) }catch(err){ console.log(err) console.log('Could not start Matrix bot, please run "npm install matrix-js-sdk" inside the Shinobi folder.') } } }