diff options
| author | fiaxh <git@lightrise.org> | 2026-08-22 21:02:05 +0200 |
|---|---|---|
| committer | fiaxh <git@lightrise.org> | 2026-10-23 16:22:06 +0200 |
| commit | deea3cae8e848388ee962a92de58dc42b77915d1 (patch) | |
| tree | 48cc3b5f2c2b1c71cdaeaac869ff8145d0fa1bd6 /libdino | |
| parent | 8d49d83b3b45ab22d7b9d945c4b32296b07cb49e (diff) | |
Store MUC features only in EntityInfo (not in MucFlag), update on change
Diffstat (limited to 'libdino')
| -rw-r--r-- | libdino/meson.build | 1 | ||||
| -rw-r--r-- | libdino/src/service/entity_capabilities_storage.vala | 71 | ||||
| -rw-r--r-- | libdino/src/service/entity_info.vala | 31 | ||||
| -rw-r--r-- | libdino/src/service/message_processor.vala | 8 | ||||
| -rw-r--r-- | libdino/src/service/module_manager.vala | 1 | ||||
| -rw-r--r-- | libdino/src/service/muc_manager.vala | 49 |
6 files changed, 49 insertions, 112 deletions
diff --git a/libdino/meson.build b/libdino/meson.build index bf29dbf9..12665b18 100644 --- a/libdino/meson.build +++ b/libdino/meson.build @@ -55,7 +55,6 @@ sources = files( 'src/service/conversation_manager.vala', 'src/service/counterpart_interaction_manager.vala', 'src/service/database.vala', - 'src/service/entity_capabilities_storage.vala', 'src/service/entity_info.vala', 'src/service/fallback_body.vala', 'src/service/file_manager.vala', diff --git a/libdino/src/service/entity_capabilities_storage.vala b/libdino/src/service/entity_capabilities_storage.vala deleted file mode 100644 index c6d0bbbd..00000000 --- a/libdino/src/service/entity_capabilities_storage.vala +++ /dev/null @@ -1,71 +0,0 @@ -using Gee; -using Qlite; -using Xmpp; -using Xmpp.Xep.ServiceDiscovery; - -namespace Dino { - -public class EntityCapabilitiesStorage : Xep.EntityCapabilities.Storage, Object { - - private Database db; - private HashMap<string, Gee.List<string>> features_cache = new HashMap<string, Gee.List<string>>(); - private HashMap<string, Identity> identity_cache = new HashMap<string, Identity>(); - - public EntityCapabilitiesStorage(Database db) { - this.db = db; - } - - public void store_features(string entity, Gee.List<string> features) { - if (features_cache.has_key(entity)) return; - - foreach (string feature in features) { - db.entity_feature.insert() - .value(db.entity_feature.entity, entity) - .value(db.entity_feature.feature, feature) - .perform(); - } - } - - public void store_identities(string entity, Gee.Set<Identity> identities) { - foreach (Identity identity in identities) { - if (identity.category == Identity.CATEGORY_CLIENT) { - db.entity_identity.insert() - .value(db.entity_identity.entity, entity) - .value(db.entity_identity.category, identity.category) - .value(db.entity_identity.type, identity.type_) - .value(db.entity_identity.entity_name, identity.name) - .perform(); - return; - } - } - } - - public Gee.List<string> get_features(string entity) { - Gee.List<string>? features = features_cache[entity]; - if (features != null) { - return features; - } - - features = new ArrayList<string>(); - foreach (Row row in db.entity_feature.select({db.entity_feature.feature}).with(db.entity_feature.entity, "=", entity)) { - features.add(row[db.entity_feature.feature]); - } - features_cache[entity] = features; - return features; - } - - public Identity? get_identities(string entity) { - Identity? identity = identity_cache[entity]; - if (identity != null) { - return identity; - } - - RowOption row = db.entity_identity.select().with(db.entity_identity.entity, "=", entity).single().row(); - if (row.is_present()) { - identity = new Identity(row[db.entity_identity.category], row[db.entity_identity.type], row[db.entity_identity.entity_name]); - } - identity_cache[entity] = identity; - return identity; - } -} -} diff --git a/libdino/src/service/entity_info.vala b/libdino/src/service/entity_info.vala index 53d14b15..03828d1d 100644 --- a/libdino/src/service/entity_info.vala +++ b/libdino/src/service/entity_info.vala @@ -12,7 +12,6 @@ public class EntityInfo : StreamInteractionModule, Object { private StreamInteractor stream_interactor; private Database db; - private EntityCapabilitiesStorage entity_capabilities_storage; private Dino.Entities.Settings settings; private HashMap<Jid, string> entity_caps_hashes = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func); @@ -40,7 +39,6 @@ public class EntityInfo : StreamInteractionModule, Object { private EntityInfo(StreamInteractor stream_interactor, Database db, Dino.Entities.Settings settings) { this.stream_interactor = stream_interactor; this.db = db; - this.entity_capabilities_storage = new EntityCapabilitiesStorage(db); this.settings = settings; stream_interactor.account_added.connect(on_account_added); @@ -58,18 +56,32 @@ public class EntityInfo : StreamInteractionModule, Object { Timeout.add_seconds(60 * 60, () => { remove_old_entities(); return true; }); } - public async Gee.Set<Identity>? get_identities(Account account, Jid jid) { + public Gee.Set<Identity>? get_identities_offline(Account account, Jid jid) { if (jid_identity.has_key(jid)) { return jid_identity[jid]; } - string? hash = entity_caps_hashes[jid]; - if (hash != null) { - Gee.Set<Identity>? identities = get_stored_identities(hash); - if (identities != null) return identities; + var qry = db.entity.select() + .with(db.entity.account_id, "=", account.id) + .with(db.entity.jid_id, "=", db.get_jid_id(jid)) + .with(db.entity.resource, "=", jid.resourcepart ?? "") + .join_with(db.entity_identity, db.entity.caps_hash, db.entity_identity.entity); + + HashSet<Identity> identities = new HashSet<Identity>(Identity.hash_func, Identity.equals_func); + + foreach (Row row in qry) { + var identity = new Identity(row[db.entity_identity.category], row[db.entity_identity.type], row[db.entity_identity.entity_name]); + identities.add(identity); } - ServiceDiscovery.InfoResult? info_result = yield get_info_result(account, jid, hash); + return identities; + } + + public async Gee.Set<Identity>? get_identities(Account account, Jid jid) { + var identities = get_identities_offline(account, jid); + if (identities != null) return identities; + + ServiceDiscovery.InfoResult? info_result = yield get_info_result(account, jid, entity_caps_hashes[jid]); if (info_result != null) { return info_result.identities; } @@ -261,7 +273,7 @@ public class EntityInfo : StreamInteractionModule, Object { return identities; } - private async ServiceDiscovery.InfoResult? get_info_result(Account account, Jid jid, string? hash = null) { + public async ServiceDiscovery.InfoResult? get_info_result(Account account, Jid jid, string? hash = null) { XmppStream? stream = stream_interactor.get_stream(account); if (stream == null) return null; @@ -298,7 +310,6 @@ public class EntityInfo : StreamInteractionModule, Object { } private void initialize_modules(Account account, ArrayList<XmppStreamModule> modules) { - modules.add(new Xep.EntityCapabilities.Module(entity_capabilities_storage)); var entity_time_module = modules.first_match((it) => it is EntityTime.Module) as EntityTime.Module; if (entity_time_module != null) { settings.bind_property("share-time", entity_time_module, "enabled", BindingFlags.SYNC_CREATE); diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala index b9c23240..9190cd9d 100644 --- a/libdino/src/service/message_processor.vala +++ b/libdino/src/service/message_processor.vala @@ -472,12 +472,8 @@ public class MessageProcessor : StreamInteractionModule, Object { // Set an origin ID if a MUC doen't guarantee to keep IDs if (conversation.type_ == Conversation.Type.GROUPCHAT) { - Xep.Muc.Flag? flag = stream.get_flag(Xep.Muc.Flag.IDENTITY); - if (flag == null) { - message.marked = Entities.Message.Marked.UNSENT; - return; - } - if(!flag.has_room_feature(conversation.counterpart, Xep.Muc.Feature.STABLE_ID)) { + var supports_stable_ids = stream_interactor.get_module(EntityInfo.IDENTITY).has_feature_cached(conversation.account, conversation.counterpart, Xep.Muc.FEATURE_STABLE_ID); + if(!supports_stable_ids) { UniqueStableStanzaIDs.set_origin_id(new_message, message.stanza_id); } } diff --git a/libdino/src/service/module_manager.vala b/libdino/src/service/module_manager.vala index 5ba4fe80..f7cad0fe 100644 --- a/libdino/src/service/module_manager.vala +++ b/libdino/src/service/module_manager.vala @@ -69,6 +69,7 @@ public class ModuleManager { module_map[account].add(new Presence.Module()); module_map[account].add(new Xmpp.MessageModule()); module_map[account].add(new Xmpp.MessageArchiveManagement.Module()); + module_map[account].add(new Xep.EntityCapabilities.Module()); module_map[account].add(new Xep.MessageCarbons.Module()); module_map[account].add(new Xep.BitsOfBinary.Module()); module_map[account].add(new Xep.Muc.Module()); diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala index b47a52bf..4959074b 100644 --- a/libdino/src/service/muc_manager.vala +++ b/libdino/src/service/muc_manager.vala @@ -108,19 +108,11 @@ public class MucManager : StreamInteractionModule, Object { joined_conversation.nickname = nick; stream_interactor.get_module(ConversationManager.IDENTITY).start_conversation(joined_conversation); - bool can_do_affiliation_versioning = yield entity_info.has_feature(account, jid, Xmpp.Xep.MucAffiliationsVersioning.NS_URI); - if (!can_do_affiliation_versioning) { - stream.get_module(Xep.Muc.Module.IDENTITY).fetch_affiliations.begin(stream, jid.bare_jid, () => { - muc_affiliations.clear_affiliations(account, jid); - persist_muc_affiliations(account, jid.bare_jid); - }); - } - if (can_do_mam) { var history_sync = stream_interactor.get_module(MessageProcessor.IDENTITY).history_sync; if (conversation == null) { // We never joined the conversation before, just fetch the latest MAM page - yield history_sync.fetch_latest_page(account, jid.bare_jid, null, new DateTime.from_unix_utc(0), cancellable); + history_sync.fetch_latest_page.begin(account, jid.bare_jid, null, new DateTime.from_unix_utc(0), cancellable); } else { // Fetch everything up to the last time the user actively joined if (!mucs_sync_cancellables.has_key(account)) { @@ -137,6 +129,17 @@ public class MucManager : StreamInteractionModule, Object { } } } + + bool can_do_affiliation_versioning = yield entity_info.has_feature(account, jid, Xmpp.Xep.MucAffiliationsVersioning.NS_URI); + if (!can_do_affiliation_versioning) { + stream.get_module(Xep.Muc.Module.IDENTITY).fetch_affiliations.begin(stream, jid.bare_jid, () => { + muc_affiliations.clear_affiliations(account, jid); + persist_muc_affiliations(account, jid.bare_jid); + }); + } + + room_info_updated(account, jid); // EntityInfo.has_feature trigged a disco query + } else if (res.muc_error != null) { // Join failed enter_errors[jid] = res.muc_error; @@ -254,19 +257,11 @@ public class MucManager : StreamInteractionModule, Object { //the term `private room` is a short hand for members-only+non-anonymous rooms public bool is_private_room(Account account, Jid jid) { var entity_info = stream_interactor.get_module(EntityInfo.IDENTITY); - return entity_info.has_feature_offline(account, jid, "muc_membersonly") && entity_info.has_feature_offline(account, jid, "muc_nonanonymous"); + return entity_info.has_feature_offline(account, jid, Xep.Muc.FEATURE_MEMBERS_ONLY) && entity_info.has_feature_offline(account, jid, Xep.Muc.FEATURE_NON_ANONYMOUS); } public bool is_moderated_room(Account account, Jid jid) { - XmppStream? stream = stream_interactor.get_stream(account); - if (stream == null) { - return false; - } - Xep.Muc.Flag? flag = stream.get_flag(Xep.Muc.Flag.IDENTITY); - if (flag == null) { - return false; - } - return flag.has_room_feature(jid, Xep.Muc.Feature.MODERATED); + return stream_interactor.get_module(EntityInfo.IDENTITY).has_feature_cached(account, jid, Xep.Muc.FEATURE_MODERATED); } public bool is_public_room(Account account, Jid jid) { @@ -332,9 +327,13 @@ public class MucManager : StreamInteractionModule, Object { } public string? get_room_name(Account account, Jid jid) { - Xep.Muc.Flag? flag = get_muc_flag(account); - if (flag != null) { - return flag.get_room_name(jid); + var identities = stream_interactor.get_module(EntityInfo.IDENTITY).get_identities_offline(account, jid); + if (identities == null) return null; + + foreach (var identity in identities) { + if (identity.category == "conference") { + return identity.name; + } } return null; } @@ -471,8 +470,10 @@ public class MucManager : StreamInteractionModule, Object { private_room_occupants_updated(account, muc_jid); } }); - stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).room_info_updated.connect( (stream, muc_jid) => { - room_info_updated(account, muc_jid); + stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).room_info_changed.connect( (stream, muc_jid) => { + stream_interactor.get_module(EntityInfo.IDENTITY).get_info_result.begin(account, muc_jid, null, () => { + room_info_updated(account, muc_jid); + }); }); stream_interactor.module_manager.get_module(account, Xep.OccupantIds.Module.IDENTITY).received_own_occupant_id.connect( (stream, jid, occupant_id) => { if (!own_occupant_ids.has_key(account)) { |
