[mirotalksfu] - add notifications section in settings

هذا الالتزام موجود في:
Miroslav Pejic
2025-10-19 10:59:04 +02:00
الأصل d939bed0fa
التزام ec112ece6b
14 ملفات معدلة مع 357 إضافات و83 حذوفات

عرض الملف

@@ -39,6 +39,16 @@ module.exports = class Room {
recSyncServerEndpoint: config?.media?.recording?.endpoint || '',
};
// ##########################
this.notifications = {
mode: {
email: '',
},
events: {
join: false,
},
};
this._moderator = {
video_start_privacy: false,
audio_start_muted: false,
@@ -485,6 +495,20 @@ module.exports = class Room {
}
}
// ####################################################
// ROOM NOTIFICATIONS
// ####################################################
updateRoomNotifications(data) {
log.debug('Update room notifications', data);
this.notifications = data.notifications;
}
getRoomNotifications() {
log.debug('get room notifications', this.notifications);
return this.notifications;
}
// ####################################################
// ROOM MODERATOR
// ####################################################

عرض الملف

@@ -64,7 +64,7 @@ dev dependencies: {
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
* @version 1.9.83
* @version 1.9.84
*
*/
@@ -1954,12 +1954,22 @@ function startServer() {
};
const firstJoin = room.getPeersCount() === 1;
const guestJoin = room.getPeersCount() === 2;
// SCENARIO: Notify when the first user join room and is awaiting assistance
// SCENARIO: Notify when the first user join room and is awaiting assistance (global email alert)
if (firstJoin && !widget.alert.enabled) {
nodemailer.sendEmailAlert('join', emailPayload);
}
// SCENARIO: Notify when the first guest user join room and presenter in (room email notification)
if (guestJoin) {
const notifications = room.getRoomNotifications();
log.debug('Room notifications on guest join', { notifications: notifications });
if (notifications?.mode?.email && notifications?.events?.join) {
nodemailer.sendEmailNotifications('join', emailPayload, notifications);
}
}
// SCENARIO: Notify when a user joins the widget room for expert assistance
if (firstJoin && widget.enabled && widget.alert && widget.alert.enabled && widget.roomId === room.id) {
switch (widget.alert.type) {
@@ -2529,6 +2539,27 @@ function startServer() {
}
});
socket.on('updateRoomNotifications', (dataObject, cb) => {
if (!roomExists(socket)) return;
if (config.integrations?.email?.notify !== true) {
const message =
'The email notification has been disabled. Please contact the administrator for further information.';
log.debug(message);
return cb({ error: message });
}
const data = checkXSS(dataObject);
const room = getRoom(socket);
const isPresenter = isPeerPresenter(socket.room_id, socket.id, data.peer_name, data.peer_uuid);
if (!isPresenter) return;
room.updateRoomNotifications(data);
});
socket.on('updateRoomModerator', (dataObject) => {
if (!roomExists(socket)) return;

عرض الملف

@@ -56,8 +56,16 @@ function hasPathTraversal(input) {
return false;
}
function isValidEmail(email) {
if (!email || typeof email !== 'string') return false;
const e = email.trim();
const re = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[A-Za-z]{2,}$/;
return re.test(e);
}
module.exports = {
isValidRoomName,
isValidRecFileNameFormat,
hasPathTraversal,
isValidEmail,
};

عرض الملف

@@ -647,6 +647,7 @@ module.exports = {
* Core Settings:
* -------------
* - alert : Enable/disable email alerts [true/false] (default: false)
* - notify : Enable/disable room email notifications [true/false] (default: false)
* - host : SMTP server address (default: 'smtp.gmail.com')
* - port : SMTP port (default: 587 for TLS)
* - username : SMTP auth username
@@ -670,6 +671,7 @@ module.exports = {
*/
email: {
alert: process.env.EMAIL_ALERTS_ENABLED === 'true',
notify: process.env.EMAIL_NOTIFICATIONS === 'true',
host: process.env.EMAIL_HOST || 'smtp.gmail.com',
port: parseInt(process.env.EMAIL_PORT) || 587,
username: process.env.EMAIL_USERNAME || 'your_username',
@@ -1205,6 +1207,7 @@ module.exports = {
sendEmailInvitation: process.env.SHOW_EMAIL_INVITE !== 'false',
micOptionsButton: process.env.SHOW_MIC_OPTIONS !== 'false',
tabRTMPStreamingBtn: process.env.SHOW_RTMP_TAB !== 'false',
tabNotificationsBtn: process.env.SHOW_NOTIFICATIONS_TAB !== 'false',
tabModerator: process.env.SHOW_MODERATOR_TAB !== 'false',
tabRecording: process.env.SHOW_RECORDING_TAB !== 'false',
host_only_recording: process.env.HOST_ONLY_RECORDING !== 'false',

عرض الملف

@@ -1,6 +1,7 @@
'use strict';
const nodemailer = require('nodemailer');
const { isValidEmail } = require('../Validator');
const config = require('../config');
const Logger = require('../Logger');
const log = new Logger('NodeMailer');
@@ -13,6 +14,7 @@ const APP_NAME = config.ui.brand.app.name || 'MiroTalk SFU';
const emailConfig = config.integrations?.email || {};
const EMAIL_ALERT = emailConfig.alert || false;
const EMAIL_NOTIFY = emailConfig.notify || false;
const EMAIL_HOST = emailConfig.host || false;
const EMAIL_PORT = emailConfig.port || false;
const EMAIL_USERNAME = emailConfig.username || false;
@@ -20,9 +22,10 @@ const EMAIL_PASSWORD = emailConfig.password || false;
const EMAIL_FROM = emailConfig.from || emailConfig.username;
const EMAIL_SEND_TO = emailConfig.sendTo || false;
if (EMAIL_ALERT && EMAIL_HOST && EMAIL_PORT && EMAIL_USERNAME && EMAIL_PASSWORD && EMAIL_SEND_TO) {
if ((EMAIL_ALERT || EMAIL_NOTIFY) && EMAIL_HOST && EMAIL_PORT && EMAIL_USERNAME && EMAIL_PASSWORD && EMAIL_SEND_TO) {
log.info('Email', {
alert: EMAIL_ALERT,
notify: EMAIL_NOTIFY,
host: EMAIL_HOST,
port: EMAIL_PORT,
username: EMAIL_USERNAME,
@@ -75,14 +78,50 @@ function sendEmailAlert(event, data) {
break;
}
if (subject && body) sendEmail(subject, body);
if (subject && body) {
sendEmail(subject, body);
return true;
}
return false;
}
function sendEmail(subject, body) {
function sendEmailNotifications(event, data, notifications) {
if (!EMAIL_NOTIFY || !EMAIL_HOST || !EMAIL_PORT || !EMAIL_USERNAME || !EMAIL_PASSWORD) return;
log.info('sendEmailNotifications', {
event: event,
data: data,
notifications: notifications,
});
let subject = false;
let body = false;
switch (event) {
case 'join':
subject = getJoinRoomSubject(data);
body = getJoinRoomBody(data);
break;
// left...
default:
break;
}
const emailSendTo = notifications?.mode?.email;
if (subject && body && isValidEmail(emailSendTo)) {
sendEmail(subject, body, emailSendTo);
return true;
}
log.error('sendEmailNotifications: Invalid email', { email: emailTo });
return false;
}
function sendEmail(subject, body, emailSendTo = false) {
transport
.sendMail({
from: EMAIL_FROM,
to: EMAIL_SEND_TO,
to: emailSendTo ? emailSendTo : EMAIL_SEND_TO,
subject: subject,
html: body,
})
@@ -221,4 +260,5 @@ function getCurrentDataTime() {
module.exports = {
sendEmailAlert,
sendEmailNotifications,
};