From 0b92ee2a113ca8da2d3a4d4b06056f291738b5fe Mon Sep 17 00:00:00 2001 From: fiaxh Date: Wed, 25 Mar 2026 19:19:29 +0100 Subject: Fix wrongly using message ids for MUC corrections; store original message db ids --- libdino/src/service/content_item_store.vala | 2 +- libdino/src/service/database.vala | 5 +++-- libdino/src/service/message_correction.vala | 22 ++++++++++++++++------ libdino/src/service/message_storage.vala | 17 +++++++++++++++-- 4 files changed, 35 insertions(+), 11 deletions(-) (limited to 'libdino/src/service') diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala index 11512a53..99475492 100644 --- a/libdino/src/service/content_item_store.vala +++ b/libdino/src/service/content_item_store.vala @@ -121,7 +121,7 @@ public class ContentItemStore : StreamInteractionModule, Object { Message? message = get_message_for_content_item(conversation, content_item); if (message == null) return null; - return MessageStorage.get_reference_id(message); + return stream_interactor.get_module(MessageStorage.IDENTITY).get_reference_id(message, conversation); } public Jid? get_message_sender_for_content_item(Conversation conversation, ContentItem content_item) { diff --git a/libdino/src/service/database.vala b/libdino/src/service/database.vala index 58ff3b14..54f5ab42 100644 --- a/libdino/src/service/database.vala +++ b/libdino/src/service/database.vala @@ -7,7 +7,7 @@ using Dino.Entities; namespace Dino { public class Database : Qlite.Database { - private const int VERSION = 30; + private const int VERSION = 31; public class AccountTable : Table { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; @@ -134,10 +134,11 @@ public class Database : Qlite.Database { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; public Column message_id = new Column.Integer("message_id") { unique=true }; public Column to_stanza_id = new Column.Text("to_stanza_id"); + public Column to_message_db_id = new Column.Integer("to_message_db_id") { min_version=31 }; internal MessageCorrectionTable(Database db) { base(db, "message_correction"); - init({id, message_id, to_stanza_id}); + init({id, message_id, to_stanza_id, to_message_db_id}); index("message_correction_to_stanza_id_idx", {to_stanza_id}); } } diff --git a/libdino/src/service/message_correction.vala b/libdino/src/service/message_correction.vala index 6c4383ba..2d710f1c 100644 --- a/libdino/src/service/message_correction.vala +++ b/libdino/src/service/message_correction.vala @@ -49,6 +49,7 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { db.message_correction.insert() .value(db.message_correction.message_id, message.id) .value(db.message_correction.to_stanza_id, reference_stanza_id) + .value(db.message_correction.to_message_db_id, old_message.id) .perform(); db.content_item.update() @@ -92,6 +93,12 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { public override string[] after_actions { get { return after_actions_const; } } public override async bool run(Entities.Message message, Xmpp.MessageStanza stanza, Conversation conversation) { + + string? replace_id = Xep.LastMessageCorrection.get_replace_id(stanza); + if (replace_id != null) { + message.edit_to = replace_id; // This isn't persisted here, but later after verifying that it's an allowed edit TODO? + } + // Check if we already know a newer correction for this message if (unmatched_corrections.has_key(conversation) && unmatched_corrections[conversation].size > 0) { ContentItem? remove_from_list = null; @@ -99,7 +106,7 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { foreach (var unmatched_correction_item in unmatched_corrections[conversation]) { MessageItem unmatched_correction_message_item = unmatched_correction_item as MessageItem; if (unmatched_correction_message_item != null) { - if (MessageStorage.get_reference_id(message) == unmatched_correction_message_item.message.edit_to) { + if (stream_interactor.get_module(MessageStorage.IDENTITY).get_reference_id(message, conversation) == unmatched_correction_message_item.message.edit_to) { debug("Matching original message to correction retrospectively %s", unmatched_correction_message_item.message.edit_to); remove_from_list = unmatched_correction_item; ret = process_wrong_order_correction(conversation, message, unmatched_correction_message_item); @@ -113,8 +120,6 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { if (ret != null) return ret; } - string? replace_id = Xep.LastMessageCorrection.get_replace_id(stanza); - // Store the latest message for every resource. This enables the corrections-allowed-check specified in the XEP. // This is only needed for MUCs - In case the MUC doesn't support occupant ids, the last message can still be corrected. if (replace_id == null && conversation.type_.is_muc_semantic()) { @@ -129,7 +134,6 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { } if (replace_id != null) { - message.edit_to = replace_id; // This isn't persisted here, but later after verifying that it's an allowed edit TODO? return process_unverified_in_order_correction(conversation, message, replace_id); } return false; @@ -140,10 +144,14 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { return false; } - db.message_correction.insert() + var qry = db.message_correction.insert() .value(db.message_correction.message_id, correction_item.message.id) - .value(db.message_correction.to_stanza_id, correction_item.message.edit_to) + .value(db.message_correction.to_stanza_id, correction_item.message.edit_to); + if (earlier_message.edit_to == null) { + // If this is the original message, link the id + qry.value(db.message_correction.to_message_db_id, earlier_message.id) .perform(); + } db.content_item.update() .with(db.content_item.id, "=", correction_item.id) @@ -171,6 +179,7 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { Message? original_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(replace_id, conversation); if (original_message != null && is_correction_acceptable(original_message, correction_message)) { correction_message.edit_to = replace_id; + correction_message.edit_to_id = original_message.id; return process_in_order_correction(conversation, original_message, correction_message); } return false; @@ -182,6 +191,7 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { db.message_correction.insert() .value(db.message_correction.message_id, correction_message.id) .value(db.message_correction.to_stanza_id, correction_message.edit_to) + .value(db.message_correction.to_message_db_id, original_message.id) .perform(); int current_correction_message_id = get_latest_correction_message_id(conversation, original_message); diff --git a/libdino/src/service/message_storage.vala b/libdino/src/service/message_storage.vala index 59e43d32..d6b8d6e3 100644 --- a/libdino/src/service/message_storage.vala +++ b/libdino/src/service/message_storage.vala @@ -204,8 +204,21 @@ public class MessageStorage : StreamInteractionModule, Object { } } - public static string? get_reference_id(Message message) { - if (message.edit_to != null) return message.edit_to; + public string? get_reference_id(Message message, Conversation conversation) { + if (message.edit_to != null) { + // This is a message edit, so the reference id should be the one of the original message + if (message.type_ == Message.Type.CHAT) { + return message.edit_to; + } else { + if (message.edit_to_id != 0) { + Message original_message = get_message_by_id(message.edit_to_id, conversation); + return original_message.server_id; + } else { + // We don't know the original message, so taking the server id of the correction is the best we can do + return message.server_id; + } + } + } if (message.type_ == Message.Type.CHAT) { return message.stanza_id; -- cgit v1.3