diff --git a/src/messaging/create.js b/src/messaging/create.js index fe0fbb7de0..87ec24729f 100644 --- a/src/messaging/create.js +++ b/src/messaging/create.js @@ -44,6 +44,7 @@ module.exports = function (Messaging) { const mid = await db.incrObjectField('global', 'nextMid'); const timestamp = data.timestamp || Date.now(); let message = { + mid: mid, content: String(data.content), timestamp: timestamp, fromuid: uid, @@ -65,6 +66,7 @@ module.exports = function (Messaging) { const tasks = [ Messaging.addMessageToRoom(roomId, mid, timestamp), Messaging.markRead(uid, roomId), + db.sortedSetAdd('messages:mid', timestamp, mid), ]; if (roomData.public) { tasks.push( diff --git a/src/messaging/data.js b/src/messaging/data.js index 38c2e7761a..3542de799f 100644 --- a/src/messaging/data.js +++ b/src/messaging/data.js @@ -7,7 +7,7 @@ const user = require('../user'); const utils = require('../utils'); const plugins = require('../plugins'); -const intFields = ['timestamp', 'edited', 'fromuid', 'roomId', 'deleted', 'system']; +const intFields = ['mid', 'timestamp', 'edited', 'fromuid', 'roomId', 'deleted', 'system']; module.exports = function (Messaging) { Messaging.newMessageCutoff = 1000 * 60 * 3; @@ -71,8 +71,6 @@ module.exports = function (Messaging) { message.newSet = false; message.roomId = String(message.roomId || roomId); - message.deleted = !!message.deleted; - message.system = !!message.system; }); messages = await Promise.all(messages.map(async (message) => { @@ -143,9 +141,6 @@ async function modifyMessage(message, fields, mid) { if (message.hasOwnProperty('edited')) { message.editedISO = utils.toISOString(message.edited); } - if (!fields.length || fields.includes('mid')) { - message.mid = parseInt(mid, 10); - } } const payload = await plugins.hooks.fire('filter:messaging.getFields', { diff --git a/src/messaging/delete.js b/src/messaging/delete.js index aca7570c34..1c16ceddc1 100644 --- a/src/messaging/delete.js +++ b/src/messaging/delete.js @@ -9,20 +9,23 @@ module.exports = function (Messaging) { async function doDeleteRestore(mid, state, uid) { const field = state ? 'deleted' : 'restored'; - const { content, deleted, roomId } = await Messaging.getMessageFields(mid, ['deleted', 'roomId', 'content']); - if (deleted === state) { + const msgData = await Messaging.getMessageFields(mid, [ + 'mid', 'fromuid', 'deleted', 'roomId', 'content', 'system', + ]); + if (msgData.deleted === state) { throw new Error(`[[error:chat-${field}-already]]`); } await Messaging.setMessageField(mid, 'deleted', state); - const ioRoom = sockets.in(`chat_room_${roomId}`); + msgData.deleted = state; + const ioRoom = sockets.in(`chat_room_${msgData.roomId}`); if (state === 1 && ioRoom) { ioRoom.emit('event:chats.delete', mid); - plugins.hooks.fire('action:messaging.delete', { message: { mid, content, deleted: 1, roomId } }); + plugins.hooks.fire('action:messaging.delete', { message: msgData }); } else if (state === 0 && ioRoom) { - const messages = await Messaging.getMessagesData([mid], uid, roomId, true); + const messages = await Messaging.getMessagesData([mid], uid, msgData.roomId, true); ioRoom.emit('event:chats.restore', messages[0]); - plugins.hooks.fire('action:messaging.restore', { message: { ...messages[0], content } }); + plugins.hooks.fire('action:messaging.restore', { message: msgData }); } } }; diff --git a/src/messaging/edit.js b/src/messaging/edit.js index bd930f9ae9..438d43685a 100644 --- a/src/messaging/edit.js +++ b/src/messaging/edit.js @@ -31,7 +31,9 @@ module.exports = function (Messaging) { sockets.in(`chat_room_${roomId}`).emit('event:chats.edit', { messages: messages, }); - plugins.hooks.fire('action:messaging.edit', { message: messages[0] }); + plugins.hooks.fire('action:messaging.edit', { + message: { ...messages[0], content: payload.content }, + }); }; const canEditDelete = async (messageId, uid, type) => { diff --git a/src/upgrades/3.3.0/chat_message_mids.js b/src/upgrades/3.3.0/chat_message_mids.js new file mode 100644 index 0000000000..ebb79324fa --- /dev/null +++ b/src/upgrades/3.3.0/chat_message_mids.js @@ -0,0 +1,45 @@ +'use strict'; + + +const db = require('../../database'); +const batch = require('../../batch'); + + +module.exports = { + name: 'Set mid on message objects and create messages:mid', + timestamp: Date.UTC(2023, 6, 27), + method: async function () { + const { progress } = this; + + progress.total = await db.sortedSetCard(`chat:rooms`); + await batch.processSortedSet(`chat:rooms`, async (roomIds) => { + progress.incr(roomIds.length); + await Promise.all(roomIds.map(async (roomId) => { + await batch.processSortedSet(`chat:room:${roomId}:mids`, async (mids) => { + let messageData = await db.getObjects(mids.map(mid => `message:${mid}`)); + messageData.forEach((m, idx) => { + if (m) { + m.mid = parseInt(mids[idx], 10); + } + }); + messageData = messageData.filter(Boolean); + + const bulkSet = messageData.map( + msg => [`message:${msg.mid}`, { mid: msg.mid }] + ); + + await db.setObjectBulk(bulkSet); + await db.sortedSetAdd( + 'messages:mid', + messageData.map(msg => msg.timestamp), + messageData.map(msg => msg.mid) + ); + }, { + batch: 500, + }); + })); + }, { + batch: 500, + }); + }, +};