From d625058d76efc9e344dd5e1239a4b040a7d2519a Mon Sep 17 00:00:00 2001 From: fiaxh Date: Wed, 17 Sep 2025 17:47:36 +0200 Subject: Message correction: Use occupant ids, handle correction-before-message --- libdino/meson.build | 1 + libdino/src/application.vala | 1 + libdino/src/entity/message.vala | 18 ++++ libdino/src/service/content_item_store.vala | 23 +++-- libdino/src/service/database.vala | 19 +++- libdino/src/service/message_correction.vala | 140 ++++++++++++++++++++++------ libdino/src/service/message_storage.vala | 4 + libdino/src/service/occupant_id_store.vala | 88 +++++++++++++++++ libdino/src/service/reactions.vala | 20 +--- libdino/src/service/replies.vala | 2 +- 10 files changed, 254 insertions(+), 62 deletions(-) create mode 100644 libdino/src/service/occupant_id_store.vala diff --git a/libdino/meson.build b/libdino/meson.build index c84eafc3..c5351228 100644 --- a/libdino/meson.build +++ b/libdino/meson.build @@ -64,6 +64,7 @@ sources = files( 'src/service/module_manager.vala', 'src/service/muc_manager.vala', 'src/service/notification_events.vala', + 'src/service/occupant_id_store.vala', 'src/service/presence_manager.vala', 'src/service/replies.vala', 'src/service/reactions.vala', diff --git a/libdino/src/application.vala b/libdino/src/application.vala index 4aa4b8ad..de1325ad 100644 --- a/libdino/src/application.vala +++ b/libdino/src/application.vala @@ -41,6 +41,7 @@ public interface Application : GLib.Application { BlockingManager.start(stream_interactor); Calls.start(stream_interactor, db); ConversationManager.start(stream_interactor, db); + OccupantIdStore.start(stream_interactor, db); MucManager.start(stream_interactor); AvatarManager.start(stream_interactor, db); RosterManager.start(stream_interactor, db); diff --git a/libdino/src/entity/message.vala b/libdino/src/entity/message.vala index 4de17125..0d53fd70 100644 --- a/libdino/src/entity/message.vala +++ b/libdino/src/entity/message.vala @@ -46,6 +46,7 @@ public class Message : Object { } public bool direction { get; set; } public Jid? real_jid { get; set; } + public int occupant_db_id { get; set; default=-1; } public Type type_ { get; set; default = Type.UNKNOWN; } private string? body_; public string? body { @@ -105,9 +106,12 @@ public class Message : Object { body = row[db.message.body]; marked = (Message.Marked) row[db.message.marked]; encryption = (Encryption) row[db.message.encryption]; + string? real_jid_str = row[db.real_jid.real_jid]; if (real_jid_str != null) real_jid = new Jid(real_jid_str); + occupant_db_id = row[db.message_occupant_id.occupant_id]; + edit_to = row[db.message_correction.to_stanza_id]; quoted_item_id = row[db.reply.quoted_content_item_id]; @@ -140,6 +144,13 @@ public class Message : Object { .value(db.real_jid.real_jid, real_jid.to_string()) .perform(); } + + if (occupant_db_id != -1) { + db.message_occupant_id.insert() + .value(db.message_occupant_id.occupant_id, occupant_db_id) + .value(db.message_occupant_id.message_id, id) + .perform(); + } notify.connect(on_update); } @@ -320,6 +331,13 @@ public class Message : Object { .value(db.reply.quoted_content_item_id, quoted_item_id) .perform(); } + + if (sp.get_name() == "message-occupant-id" && occupant_db_id != -1) { + db.message_occupant_id.upsert() + .value(db.message_occupant_id.occupant_id, occupant_db_id, true) + .value(db.message_occupant_id.message_id, id) + .perform(); + } } } diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala index 7d7ed1fb..b3ec5d67 100644 --- a/libdino/src/service/content_item_store.vala +++ b/libdino/src/service/content_item_store.vala @@ -148,31 +148,26 @@ public class ContentItemStore : StreamInteractionModule, Object { return null; } - public ContentItem? get_content_item_for_message_id(Conversation conversation, string message_id) { - Row? row = get_content_item_row_for_message_id(conversation, message_id); + public ContentItem? get_content_item_for_referencing_id(Conversation conversation, string message_id) { + Row? row = get_content_item_row_for_referencing_id(conversation, message_id); if (row != null) { return get_item_from_row(row, conversation); } return null; } - public int get_content_item_id_for_message_id(Conversation conversation, string message_id) { - Row? row = get_content_item_row_for_message_id(conversation, message_id); + public int get_content_item_id_for_referencing_id(Conversation conversation, string message_id) { + Row? row = get_content_item_row_for_referencing_id(conversation, message_id); if (row != null) { return row[db.content_item.id]; } return -1; } - private Row? get_content_item_row_for_message_id(Conversation conversation, string message_id) { + private Row? get_content_item_row_for_referencing_id(Conversation conversation, string message_id) { var content_item_row = db.content_item.select(); - Message? message = null; - if (conversation.type_ == Conversation.Type.CHAT) { - message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(message_id, conversation); - } else { - message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(message_id, conversation); - } + Message? message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_referencing_id(message_id, conversation); if (message == null) return null; RowOption file_transfer_row = db.file_transfer.select() @@ -186,7 +181,11 @@ public class ContentItemStore : StreamInteractionModule, Object { content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id]) .with(db.content_item.content_type, "=", 2); } else { - content_item_row.with(db.content_item.foreign_id, "=", message.id) + // Check if this message has been corrected. In that case, the foreign id is the latest correction. + int correction_message_db_id = stream_interactor.get_module(MessageCorrection.IDENTITY).get_latest_correction_message_id(conversation, message_id); + int message_db_id = correction_message_db_id != -1 ? correction_message_db_id : message.id; + + content_item_row.with(db.content_item.foreign_id, "=", message_db_id) .with(db.content_item.content_type, "=", 1); } RowOption content_item_row_option = content_item_row.single().row(); diff --git a/libdino/src/service/database.vala b/libdino/src/service/database.vala index e47e24e9..58ff3b14 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 = 29; + private const int VERSION = 30; public class AccountTable : Table { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; @@ -103,6 +103,19 @@ public class Database : Qlite.Database { } } + public class MessageOccupantId : Table { + public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; + public Column message_id = new Column.Integer("message_id") { not_null = true }; + public Column occupant_id = new Column.Integer("occupant_id") { not_null = true }; + + internal MessageOccupantId(Database db) { + base(db, "message_occupant_id"); + init({id, message_id, occupant_id}); + + index("message_id_occupant_id", { message_id, occupant_id }); + } + } + public class BodyMeta : Table { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; public Column message_id = new Column.Integer("message_id"); @@ -440,6 +453,7 @@ public class Database : Qlite.Database { public EntityTable entity { get; private set; } public ContentItemTable content_item { get; private set; } public MessageTable message { get; private set; } + public MessageOccupantId message_occupant_id { get; private set; } public BodyMeta body_meta { get; private set; } public ReplyTable reply { get; private set; } public MessageCorrectionTable message_correction { get; private set; } @@ -473,6 +487,7 @@ public class Database : Qlite.Database { entity = new EntityTable(this); content_item = new ContentItemTable(this); message = new MessageTable(this); + message_occupant_id = new MessageOccupantId(this); body_meta = new BodyMeta(this); message_correction = new MessageCorrectionTable(this); reply = new ReplyTable(this); @@ -494,7 +509,7 @@ public class Database : Qlite.Database { settings = new SettingsTable(this); account_settings = new AccountSettingsTable(this); conversation_settings = new ConversationSettingsTable(this); - init({ account, jid, entity, content_item, message, body_meta, message_correction, reply, real_jid, occupantid, file_transfer, file_hashes, file_thumbnails, sfs_sources, call, call_counterpart, conversation, avatar, entity_identity, entity_feature, roster, mam_catchup, reaction, settings, account_settings, conversation_settings }); + init({ account, jid, entity, content_item, message, message_occupant_id, body_meta, message_correction, reply, real_jid, occupantid, file_transfer, file_hashes, file_thumbnails, sfs_sources, call, call_counterpart, conversation, avatar, entity_identity, entity_feature, roster, mam_catchup, reaction, settings, account_settings, conversation_settings }); try { exec("PRAGMA journal_mode = WAL"); diff --git a/libdino/src/service/message_correction.vala b/libdino/src/service/message_correction.vala index 08145a6b..191f737f 100644 --- a/libdino/src/service/message_correction.vala +++ b/libdino/src/service/message_correction.vala @@ -16,8 +16,9 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { private StreamInteractor stream_interactor; private Database db; - private HashMap> last_messages = new HashMap>(Conversation.hash_func, Conversation.equals_func); + public HashMap> unmatched_corrections = new HashMap>(Conversation.hash_func, Conversation.equals_func); + private HashMap> last_messages = new HashMap>(Conversation.hash_func, Conversation.equals_func); private HashMap outstanding_correction_nodes = new HashMap(); public static void start(StreamInteractor stream_interactor, Database db) { @@ -37,6 +38,7 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { if (last_messages.has_key(conversation)) last_messages[conversation].unset(jid); } }); + stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(cache_unmatched_correction); } public void set_correction(Conversation conversation, Message message, Message old_message) { @@ -90,51 +92,110 @@ 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) { - if (conversation.type_ != Conversation.Type.CHAT) { - // Don't process messages or corrections from MUC history or MUC MAM - DateTime? mam_delay = Xep.DelayedDelivery.get_time_for_message(stanza, message.from.bare_jid); - if (mam_delay != null) return false; - if (Xmpp.MessageArchiveManagement.MessageFlag.get_flag(stanza) != null) return false; + if (unmatched_corrections.has_key(conversation) && unmatched_corrections[conversation].size > 0) { + ContentItem? remove_from_list = null; + bool? ret = null; + 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) { + 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); + } else if (unmatched_correction_message_item.message.edit_to == message.edit_to) { + debug("Got another correction to the same (unknown) original message %s", message.edit_to); + ret = process_wrong_order_correction(conversation, message, unmatched_correction_message_item); + } + } + } + if (remove_from_list != null) unmatched_corrections[conversation].remove(remove_from_list); + if (ret != null) return ret; } string? replace_id = Xep.LastMessageCorrection.get_replace_id(stanza); - if (replace_id == null) { - if (!last_messages.has_key(conversation)) { - last_messages[conversation] = new HashMap(Jid.hash_func, Jid.equals_func); + + // 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()) { + // Don't process messages or corrections from MUC history or MUC MAM + if (Xep.DelayedDelivery.get_time_for_message(stanza, message.from.bare_jid) == null && + Xmpp.MessageArchiveManagement.MessageFlag.get_flag(stanza) == null) { + if (!last_messages.has_key(conversation)) { + last_messages[conversation] = new HashMap(Jid.hash_func, Jid.equals_func); + } + last_messages[conversation][message.from] = message; } - last_messages[conversation][message.from] = message; + } + + if (replace_id != null) { + var correction_message = message; + correction_message.edit_to = replace_id; // This isn't persisted TODO + + // Check if it's maybe accepted by the XEP rules (for MUCs without occupant id) + if (conversation.type_.is_muc_semantic()) { + if (last_messages.has_key(conversation) && last_messages[conversation].has_key(correction_message.from)) { + var last_message = last_messages[conversation][correction_message.from]; + // TODO this should be the referencing id (-> in MUCs the server id), but this implementation is temporarily for backwards-compatibility. + bool acceptable = last_message.stanza_id == replace_id || last_message.server_id == replace_id; + if (acceptable) { + return process_in_order_correction(conversation, last_messages[conversation][correction_message.from], correction_message); + } + } + } + + Message? original_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_referencing_id(replace_id, conversation); + if (original_message != null && is_correction_acceptable(original_message, correction_message)) { + return process_in_order_correction(conversation, original_message, correction_message); + } + return false; + } + return false; + } + private bool process_wrong_order_correction(Conversation conversation, Message earlier_message, MessageItem correction_message) { + if (!is_correction_acceptable(earlier_message, correction_message.message)) { return false; } - if (!last_messages.has_key(conversation) || !last_messages[conversation].has_key(message.from)) return false; - Message original_message = last_messages[conversation][message.from]; - // TODO this should be the referencing id (-> in MUCs the server id), but this implementation is temporarily for backwards-compatibility. - if (original_message.stanza_id != replace_id && original_message.server_id != replace_id) return false; + db.content_item.update() + .with(db.content_item.id, "=", correction_message.id) + .set(db.content_item.time, (long) earlier_message.time.to_unix()) + .set(db.content_item.local_time, (long) earlier_message.local_time.to_unix()) + .perform(); + + correction_message.time = earlier_message.time; - int message_id_to_be_updated = get_latest_correction_message_id(conversation.account.id, replace_id, db.get_jid_id(message.counterpart), message.counterpart.resourcepart); + on_received_correction(conversation, correction_message.message.id); + + return true; + } + + private bool process_in_order_correction(Conversation conversation, Message original_message, Message correction_message) { + int message_id_to_be_updated = get_latest_correction_message_id(conversation, correction_message.edit_to); if (message_id_to_be_updated == -1) { message_id_to_be_updated = original_message.id; } - db.message_correction.insert() - .value(db.message_correction.message_id, message.id) - .value(db.message_correction.to_stanza_id, replace_id) - .perform(); + ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_referencing_id(conversation, correction_message.edit_to); - int current_correction_message_id = get_latest_correction_message_id(conversation.account.id, replace_id, db.get_jid_id(message.counterpart), message.counterpart.resourcepart); + db.message_correction.insert() + .value(db.message_correction.message_id, correction_message.id) + .value(db.message_correction.to_stanza_id, correction_message.edit_to) + .perform(); - if (current_correction_message_id != message_id_to_be_updated) { + int current_correction_message_id = get_latest_correction_message_id(conversation, correction_message.edit_to); + if (content_item != null) { db.content_item.update() - .with(db.content_item.foreign_id, "=", message_id_to_be_updated) + .with(db.content_item.id, "=", content_item.id) .with(db.content_item.content_type, "=", 1) .set(db.content_item.foreign_id, current_correction_message_id) .perform(); - message.edit_to = replace_id; on_received_correction(conversation, current_correction_message_id); return true; + } else { + warning("Got no content item for %s", correction_message.edit_to); } return false; @@ -147,16 +208,16 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { } } - private int get_latest_correction_message_id(int account_id, string stanza_id, int counterpart_jid_id, string? counterpart_resource) { + public int get_latest_correction_message_id(Conversation conversation, string stanza_ref_id) { var qry = db.message_correction.select({db.message.id}) .join_with(db.message, db.message.id, db.message_correction.message_id) - .with(db.message.account_id, "=", account_id) - .with(db.message.counterpart_id, "=", counterpart_jid_id) - .with(db.message_correction.to_stanza_id, "=", stanza_id) + .with(db.message.account_id, "=", conversation.account.id) + .with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart)) + .with(db.message_correction.to_stanza_id, "=", stanza_ref_id) .order_by(db.message.time, "DESC"); - if (counterpart_resource != null) { - qry.with(db.message.counterpart_resource, "=", counterpart_resource); + if (conversation.counterpart.resourcepart != null) { + qry.with(db.message.counterpart_resource, "=", conversation.counterpart.resourcepart); } RowOption row = qry.single().row(); if (row.is_present()) { @@ -181,6 +242,27 @@ public class MessageCorrection : StreamInteractionModule, MessageListener { last_messages[conversation] = last_conversation_messages; } } + + private void cache_unmatched_correction(ContentItem content_item, Conversation conversation) { + MessageItem message_item = content_item as MessageItem; + if (message_item == null || message_item.message.edit_to == null) return; + + // Check if this is an unmatched correction + if (content_item.time != message_item.time) return; + + debug(@"Caching unmatched correction $(message_item.message.server_id) $(message_item.id)"); + if (!unmatched_corrections.has_key(conversation)) unmatched_corrections[conversation] = new ArrayList(); + unmatched_corrections[conversation].add(content_item); + } } + // Accepts MUC corrections iff the occupant id matches + // Accepts 1:1 corrections iff the bare jid matches + private bool is_correction_acceptable(Message original_message, Message correction_message) { + bool acceptable = (original_message.type_.is_muc_semantic() && original_message.occupant_db_id != -1 && original_message.occupant_db_id == correction_message.occupant_db_id) || + (original_message.type_ == Message.Type.CHAT && original_message.from.equals_bare(correction_message.from)); + if (!acceptable) warning("Got unacceptable correction (%i to %i from %s)", correction_message.id, original_message.id, correction_message.from.to_string()); + return acceptable; + } + } diff --git a/libdino/src/service/message_storage.vala b/libdino/src/service/message_storage.vala index 81df46d5..59e43d32 100644 --- a/libdino/src/service/message_storage.vala +++ b/libdino/src/service/message_storage.vala @@ -41,6 +41,7 @@ public class MessageStorage : StreamInteractionModule, Object { .with(db.message.counterpart_id, "=", db.get_jid_id(conversation.counterpart)) .with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation)) .order_by(db.message.time, "DESC") + .outer_join_with(db.message_occupant_id, db.message_occupant_id.message_id, db.message.id) .outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id) .outer_join_with(db.reply, db.reply.message_id, db.message.id) .limit(count); @@ -92,6 +93,7 @@ public class MessageStorage : StreamInteractionModule, Object { } RowOption row_option = db.message.select().with(db.message.id, "=", id) + .outer_join_with(db.message_occupant_id, db.message_occupant_id.message_id, db.message.id) .outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id) .outer_join_with(db.reply, db.reply.message_id, db.message.id) .row(); @@ -121,6 +123,7 @@ public class MessageStorage : StreamInteractionModule, Object { .with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation)) .with(db.message.stanza_id, "=", stanza_id) .order_by(db.message.time, "DESC") + .outer_join_with(db.message_occupant_id, db.message_occupant_id.message_id, db.message.id) .outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id) .outer_join_with(db.reply, db.reply.message_id, db.message.id); @@ -147,6 +150,7 @@ public class MessageStorage : StreamInteractionModule, Object { .with(db.message.type_, "=", (int) Util.get_message_type_for_conversation(conversation)) .with(db.message.server_id, "=", server_id) .order_by(db.message.time, "DESC") + .outer_join_with(db.message_occupant_id, db.message_occupant_id.message_id, db.message.id) .outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id) .outer_join_with(db.reply, db.reply.message_id, db.message.id); diff --git a/libdino/src/service/occupant_id_store.vala b/libdino/src/service/occupant_id_store.vala new file mode 100644 index 00000000..662b9cbb --- /dev/null +++ b/libdino/src/service/occupant_id_store.vala @@ -0,0 +1,88 @@ +using Xmpp; +using Gee; +using Qlite; + +using Dino.Entities; + +namespace Dino { + + public class OccupantIdStore : StreamInteractionModule, Object { + public static ModuleIdentity IDENTITY = new ModuleIdentity("occupant_id_cache"); + public string id { get { return IDENTITY.id; } } + + private Database db; + + // (Account, MUC JID, occupant id) -> occupant db id + private HashMap>> occupant_db_ids = new HashMap>>(Account.hash_func, Account.equals_func); + private HashMap occupant_nicks = new HashMap(); + + public static void start(StreamInteractor stream_interactor, Database db) { + OccupantIdStore m = new OccupantIdStore(db); + stream_interactor.add_module(m); + } + + private OccupantIdStore(Database db) { + this.db = db; + } + + public int get_occupant_db_id(Account account, string occupant_id, Jid muc_jid) { + if (!occupant_db_ids.has_key(account) || !occupant_db_ids[account].has_key(muc_jid) || !occupant_db_ids[account][muc_jid].has_key(occupant_id)) { + warning("Requested unknown occupant db id"); + return -1; + } + + return occupant_db_ids[account][muc_jid][occupant_id]; + } + + public int cache_occupant_id(Account account, string occupant_id, Jid occupant_jid) { + string last_nick = occupant_jid.resourcepart; + Jid muc_jid = occupant_jid.bare_jid; + + if (occupant_db_ids.has_key(account) && occupant_db_ids[account].has_key(muc_jid) && occupant_db_ids[account][muc_jid].has_key(occupant_id)) { + int occupant_db_id = occupant_db_ids[account][muc_jid][occupant_id]; + if (occupant_nicks[occupant_db_id] == last_nick) { + return occupant_db_id; + } + } + + if (!occupant_db_ids.has_key(account)) occupant_db_ids[account] = new HashMap>(Jid.hash_bare_func, Jid.equals_bare_func); + if (!occupant_db_ids[account].has_key(muc_jid)) occupant_db_ids[account][muc_jid] = new HashMap(); + + int muc_jid_id = db.get_jid_id(muc_jid); + + RowOption row = db.occupantid.select() + .with(db.occupantid.account_id, "=", account.id) + .with(db.occupantid.jid_id, "=", muc_jid_id) + .with(db.occupantid.occupant_id, "=", occupant_id) + .single().row(); + + int occupant_db_id = -1; + if (row.is_present()) { + occupant_db_id = row[db.occupantid.id]; + + if (row[db.occupantid.last_nick] != last_nick) { + db.occupantid.upsert() + .value(db.occupantid.account_id, account.id, true) + .value(db.occupantid.jid_id, muc_jid_id, true) + .value(db.occupantid.occupant_id, occupant_id, true) + .value(db.occupantid.last_nick, last_nick, false) + .perform(); + } + } else { + occupant_db_id = (int)db.occupantid.upsert() + .value(db.occupantid.account_id, account.id, true) + .value(db.occupantid.jid_id, muc_jid_id, true) + .value(db.occupantid.occupant_id, occupant_id, true) + .value(db.occupantid.last_nick, muc_jid.resourcepart, false) + .perform(); + } + + occupant_db_ids[account][muc_jid][occupant_id] = occupant_db_id; + occupant_nicks[occupant_db_id] = last_nick; + + return occupant_db_id; + } + + + } +} \ No newline at end of file diff --git a/libdino/src/service/reactions.vala b/libdino/src/service/reactions.vala index 91651db7..f6050d28 100644 --- a/libdino/src/service/reactions.vala +++ b/libdino/src/service/reactions.vala @@ -251,7 +251,7 @@ public class Dino.Reactions : StreamInteractionModule, Object { Message reaction_message = yield stream_interactor.get_module(MessageProcessor.IDENTITY).parse_message_stanza(account, stanza); Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(reaction_message); - int content_item_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_id_for_message_id(conversation, message_id); + int content_item_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_id_for_referencing_id(conversation, message_id); var reaction_info = new ReactionInfo() { conversation=conversation, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() }; if (content_item_id != -1) { @@ -425,23 +425,7 @@ public class Dino.Reactions : StreamInteractionModule, Object { } if (occupant_id != null) { - RowOption row = db.occupantid.select() - .with(db.occupantid.account_id, "=", account.id) - .with(db.occupantid.jid_id, "=", jid_id) - .with(db.occupantid.occupant_id, "=", occupant_id) - .single().row(); - - int occupant_db_id = -1; - if (row.is_present()) { - occupant_db_id = row[db.occupantid.id]; - } else { - occupant_db_id = (int)db.occupantid.upsert() - .value(db.occupantid.account_id, account.id, true) - .value(db.occupantid.jid_id, jid_id, true) - .value(db.occupantid.occupant_id, occupant_id, true) - .value(db.occupantid.last_nick, jid.resourcepart, false) - .perform(); - } + int occupant_db_id = stream_interactor.get_module(OccupantIdStore.IDENTITY).cache_occupant_id(account, occupant_id, jid); builder.value(db.reaction.occupant_id, occupant_db_id, true); } diff --git a/libdino/src/service/replies.vala b/libdino/src/service/replies.vala index cc9f43cc..ea10cf88 100644 --- a/libdino/src/service/replies.vala +++ b/libdino/src/service/replies.vala @@ -64,7 +64,7 @@ public class Dino.Replies : StreamInteractionModule, Object { Xep.Replies.ReplyTo? reply_to = Xep.Replies.get_reply_to(stanza); if (reply_to == null) return; - ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_message_id(conversation, reply_to.to_message_id); + ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_referencing_id(conversation, reply_to.to_message_id); if (quoted_content_item == null) return; message.set_quoted_item(quoted_content_item.id); -- cgit v1.3