Shinobi/libs/notifications/matrix.js

387 lines
17 KiB
JavaScript

const fs = require("fs")
const fetch = require("node-fetch")
module.exports = function(s,config,lang,getSnapshot){
const {
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){
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){
const imageEventText = `${lang.Event} ${d.screenshotName} ${d.currentTimestamp}`
sendMessage({
text: imageEventText,
},[
{
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({},[
{
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.')
}
}
}