mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-06 20:41:17 +01:00
137 lines
4.4 KiB
JavaScript
137 lines
4.4 KiB
JavaScript
'use strict';
|
|
|
|
const winston = require('winston');
|
|
|
|
const batch = require('../batch');
|
|
const db = require('../database');
|
|
const notifications = require('../notifications');
|
|
const user = require('../user');
|
|
const io = require('../socket.io');
|
|
const plugins = require('../plugins');
|
|
const meta = require('../meta');
|
|
|
|
module.exports = function (Messaging) {
|
|
// Only used to notify a user of a new chat message
|
|
Messaging.notifyQueue = {};
|
|
|
|
Messaging.setUserNotificationSetting = async (uid, roomId, value) => {
|
|
if (parseInt(value, 10) === -1) {
|
|
// go back to default
|
|
return await db.deleteObjectField(`chat:room:${roomId}:notification:settings`, uid);
|
|
}
|
|
await db.setObjectField(`chat:room:${roomId}:notification:settings`, uid, parseInt(value, 10));
|
|
};
|
|
|
|
Messaging.getUidsNotificationSetting = async (uids, roomId) => {
|
|
const [settings, roomData] = await Promise.all([
|
|
db.getObjectFields(`chat:room:${roomId}:notification:settings`, uids),
|
|
Messaging.getRoomData(roomId, ['notificationSetting']),
|
|
]);
|
|
return uids.map(uid => parseInt(settings[uid] || roomData.notificationSetting, 10));
|
|
};
|
|
|
|
Messaging.markRoomNotificationsRead = async (uid, roomId) => {
|
|
const chatNids = await db.getSortedSetScan({
|
|
key: `uid:${uid}:notifications:unread`,
|
|
match: `chat_${roomId}_*`,
|
|
});
|
|
if (chatNids.length) {
|
|
await notifications.markReadMultiple(chatNids, uid);
|
|
await user.notifications.pushCount(uid);
|
|
}
|
|
};
|
|
|
|
Messaging.notifyUsersInRoom = async (fromUid, roomId, messageObj) => {
|
|
const isPublic = parseInt(await db.getObjectField(`chat:room:${roomId}`, 'public'), 10) === 1;
|
|
|
|
let data = {
|
|
roomId: roomId,
|
|
fromUid: fromUid,
|
|
message: messageObj,
|
|
public: isPublic,
|
|
};
|
|
data = await plugins.hooks.fire('filter:messaging.notify', data);
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
// delivers full message to all online users in roomId
|
|
io.in(`chat_room_${roomId}`).emit('event:chats.receive', data);
|
|
|
|
const unreadData = { roomId, fromUid, public: isPublic };
|
|
if (isPublic && !messageObj.system) {
|
|
// delivers unread public msg to all online users on the chats page
|
|
io.in(`chat_room_public_${roomId}`).emit('event:chats.public.unread', unreadData);
|
|
}
|
|
if (messageObj.system) {
|
|
return;
|
|
}
|
|
|
|
// push unread count only for private rooms
|
|
if (!isPublic) {
|
|
const uids = await Messaging.getAllUidsInRoomFromSet(`chat:room:${roomId}:uids:online`);
|
|
Messaging.pushUnreadCount(uids, unreadData);
|
|
}
|
|
|
|
// Delayed notifications
|
|
let queueObj = Messaging.notifyQueue[`${fromUid}:${roomId}`];
|
|
if (queueObj) {
|
|
queueObj.message.content += `\n${messageObj.content}`;
|
|
clearTimeout(queueObj.timeout);
|
|
} else {
|
|
queueObj = {
|
|
message: messageObj,
|
|
};
|
|
Messaging.notifyQueue[`${fromUid}:${roomId}`] = queueObj;
|
|
}
|
|
|
|
queueObj.timeout = setTimeout(async () => {
|
|
try {
|
|
await sendNotification(fromUid, roomId, queueObj.message);
|
|
delete Messaging.notifyQueue[`${fromUid}:${roomId}`];
|
|
} catch (err) {
|
|
winston.error(`[messaging/notifications] Unabled to send notification\n${err.stack}`);
|
|
}
|
|
}, meta.config.notificationSendDelay * 1000);
|
|
};
|
|
|
|
async function sendNotification(fromUid, roomId, messageObj) {
|
|
fromUid = parseInt(fromUid, 10);
|
|
|
|
const [settings, roomData] = await Promise.all([
|
|
db.getObject(`chat:room:${roomId}:notification:settings`),
|
|
Messaging.getRoomData(roomId, ['notificationSetting']),
|
|
]);
|
|
const roomDefault = roomData.notificationSetting;
|
|
const uidsToNotify = [];
|
|
const { ALLMESSAGES } = Messaging.notificationSettings;
|
|
await batch.processSortedSet(`chat:room:${roomId}:uids:online`, async (uids) => {
|
|
uids = uids.filter(
|
|
uid => (parseInt((settings && settings[uid]) || roomDefault, 10) === ALLMESSAGES) &&
|
|
fromUid !== parseInt(uid, 10)
|
|
);
|
|
const hasRead = await Messaging.hasRead(uids, roomId);
|
|
uidsToNotify.push(...uids.filter((uid, index) => !hasRead[index]));
|
|
}, {
|
|
reverse: true,
|
|
batch: 500,
|
|
interval: 100,
|
|
});
|
|
|
|
if (uidsToNotify.length) {
|
|
const { displayname } = messageObj.fromUser;
|
|
const isGroupChat = await Messaging.isGroupChat(roomId);
|
|
const notification = await notifications.create({
|
|
type: isGroupChat ? 'new-group-chat' : 'new-chat',
|
|
subject: `[[email:notif.chat.subject, ${displayname}]]`,
|
|
bodyShort: `[[notifications:new_message_from, ${displayname}]]`,
|
|
bodyLong: messageObj.content,
|
|
nid: `chat_${roomId}_${fromUid}`,
|
|
from: fromUid,
|
|
path: `/chats/${messageObj.roomId}`,
|
|
});
|
|
await notifications.push(notification, uidsToNotify);
|
|
}
|
|
}
|
|
};
|