From fe45ab575c687febc1f342b0882a7597bd6ae9dc Mon Sep 17 00:00:00 2001 From: fiaxh Date: Sun, 26 May 2024 17:21:04 +0200 Subject: Support avatar deletion --- libdino/src/service/avatar_manager.vala | 43 ++++++++++++------ plugins/omemo/src/protocol/stream_module.vala | 4 +- xmpp-vala/src/module/xep/0060_pubsub.vala | 59 +++++++++++++++++-------- xmpp-vala/src/module/xep/0084_user_avatars.vala | 15 +++++-- xmpp-vala/src/module/xep/0402_bookmarks2.vala | 2 +- 5 files changed, 85 insertions(+), 38 deletions(-) diff --git a/libdino/src/service/avatar_manager.vala b/libdino/src/service/avatar_manager.vala index 3bd38e72..f99f37d4 100644 --- a/libdino/src/service/avatar_manager.vala +++ b/libdino/src/service/avatar_manager.vala @@ -160,30 +160,32 @@ public class AvatarManager : StreamInteractionModule, Object { } } + public void unset_avatar(Account account) { + XmppStream stream = stream_interactor.get_stream(account); + if (stream == null) return; + Xmpp.Xep.UserAvatars.unset_avatar(stream); + } + private void on_account_added(Account account) { stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).received_avatar_hash.connect((stream, jid, id) => - on_user_avatar_received.begin(account, jid, id) + on_user_avatar_received(account, jid, id) ); + stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).avatar_removed.connect((stream, jid) => { + on_user_avatar_removed(account, jid); + }); stream_interactor.module_manager.get_module(account, Xep.VCard.Module.IDENTITY).received_avatar_hash.connect((stream, jid, id) => - on_vcard_avatar_received.begin(account, jid, id) + on_vcard_avatar_received(account, jid, id) ); foreach (var entry in get_avatar_hashes(account, Source.USER_AVATARS).entries) { - on_user_avatar_received.begin(account, entry.key, entry.value); + on_user_avatar_received(account, entry.key, entry.value); } foreach (var entry in get_avatar_hashes(account, Source.VCARD).entries) { - - // FIXME: remove. temporary to remove falsely saved avatars. - if (stream_interactor.get_module(MucManager.IDENTITY).is_groupchat(entry.key, account)) { - db.avatar.delete().with(db.avatar.jid_id, "=", db.get_jid_id(entry.key)).perform(); - continue; - } - - on_vcard_avatar_received.begin(account, entry.key, entry.value); + on_vcard_avatar_received(account, entry.key, entry.value); } } - private async void on_user_avatar_received(Account account, Jid jid_, string id) { + private void on_user_avatar_received(Account account, Jid jid_, string id) { Jid jid = jid_.bare_jid; if (!user_avatars.has_key(jid) || user_avatars[jid] != id) { @@ -193,7 +195,14 @@ public class AvatarManager : StreamInteractionModule, Object { received_avatar(jid, account); } - private async void on_vcard_avatar_received(Account account, Jid jid_, string id) { + private void on_user_avatar_removed(Account account, Jid jid_) { + Jid jid = jid_.bare_jid; + user_avatars.unset(jid); + remove_avatar_hash(account, jid, Source.USER_AVATARS); + received_avatar(jid, account); + } + + private void on_vcard_avatar_received(Account account, Jid jid_, string id) { bool is_gc = stream_interactor.get_module(MucManager.IDENTITY).might_be_groupchat(jid_.bare_jid, account); Jid jid = is_gc ? jid_ : jid_.bare_jid; @@ -215,6 +224,14 @@ public class AvatarManager : StreamInteractionModule, Object { .perform(); } + public void remove_avatar_hash(Account account, Jid jid, int type) { + db.avatar.delete() + .with(db.avatar.jid_id, "=", db.get_jid_id(jid)) + .with(db.avatar.account_id, "=", account.id) + .with(db.avatar.type_, "=", type) + .perform(); + } + public HashMap get_avatar_hashes(Account account, int type) { HashMap ret = new HashMap(Jid.hash_func, Jid.equals_func); foreach (Row row in db.avatar.select({db.avatar.jid_id, db.avatar.hash}) diff --git a/plugins/omemo/src/protocol/stream_module.vala b/plugins/omemo/src/protocol/stream_module.vala index b00ea5b8..4e97b1e6 100644 --- a/plugins/omemo/src/protocol/stream_module.vala +++ b/plugins/omemo/src/protocol/stream_module.vala @@ -30,8 +30,8 @@ public class StreamModule : XmppStreamModule { } public override void attach(XmppStream stream) { - stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NODE_DEVICELIST, true, - (stream, jid, id, node) => parse_device_list(stream, jid, id, node), null); + stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NODE_DEVICELIST, + (stream, jid, id, node) => parse_device_list(stream, jid, id, node), null, null); } public override void detach(XmppStream stream) { diff --git a/xmpp-vala/src/module/xep/0060_pubsub.vala b/xmpp-vala/src/module/xep/0060_pubsub.vala index 77f9aee6..c6395eb9 100644 --- a/xmpp-vala/src/module/xep/0060_pubsub.vala +++ b/xmpp-vala/src/module/xep/0060_pubsub.vala @@ -17,11 +17,12 @@ namespace Xmpp.Xep.Pubsub { private HashMap item_listeners = new HashMap(); private HashMap retract_listeners = new HashMap(); - private ArrayList pep_subset_listeners = new ArrayList(); + private HashMap delete_listeners = new HashMap(); - public void add_filtered_notification(XmppStream stream, string node, bool pep_subset, + public void add_filtered_notification(XmppStream stream, string node, owned ItemListenerDelegate.ResultFunc? item_listener, - owned RetractListenerDelegate.ResultFunc? retract_listener) { + owned RetractListenerDelegate.ResultFunc? retract_listener, + owned DeleteListenerDelegate.ResultFunc? delete_listener) { stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature_notify(stream, node); if (item_listener != null) { item_listeners[node] = new ItemListenerDelegate((owned)item_listener); @@ -29,8 +30,8 @@ namespace Xmpp.Xep.Pubsub { if (retract_listener != null) { retract_listeners[node] = new RetractListenerDelegate((owned)retract_listener); } - if (pep_subset) { - pep_subset_listeners.add(node); + if (delete_listener != null) { + delete_listeners[node] = new DeleteListenerDelegate((owned)delete_listener); } } @@ -181,30 +182,41 @@ namespace Xmpp.Xep.Pubsub { private void on_received_message(XmppStream stream, MessageStanza message) { StanzaNode event_node = message.stanza.get_subnode("event", NS_URI_EVENT); if (event_node == null) return; - StanzaNode items_node = event_node.get_subnode("items", NS_URI_EVENT); - if (items_node == null) return; - string node = items_node.get_attribute("node", NS_URI_EVENT); - if (!message.from.is_bare() && pep_subset_listeners.contains(node)) { + if (!message.from.is_bare()) { warning("Got a PEP message from a full JID (%s), ignoring.", message.from.to_string()); return; } - StanzaNode? item_node = items_node.get_subnode("item", NS_URI_EVENT); - if (item_node != null) { - string id = item_node.get_attribute("id", NS_URI_EVENT); + StanzaNode items_node = event_node.get_subnode("items", NS_URI_EVENT); + if (items_node != null) { + string node = items_node.get_attribute("node", NS_URI_EVENT); + + StanzaNode? item_node = items_node.get_subnode("item", NS_URI_EVENT); + if (item_node != null) { + string id = item_node.get_attribute("id", NS_URI_EVENT); + + if (item_listeners.has_key(node)) { + item_listeners[node].on_result(stream, message.from, id, item_node.sub_nodes[0]); + } + } + + StanzaNode? retract_node = items_node.get_subnode("retract", NS_URI_EVENT); + if (retract_node != null) { + string id = retract_node.get_attribute("id", NS_URI_EVENT); - if (item_listeners.has_key(node)) { - item_listeners[node].on_result(stream, message.from, id, item_node.sub_nodes[0]); + if (retract_listeners.has_key(node)) { + retract_listeners[node].on_result(stream, message.from, id); + } } } - StanzaNode? retract_node = items_node.get_subnode("retract", NS_URI_EVENT); - if (retract_node != null) { - string id = retract_node.get_attribute("id", NS_URI_EVENT); + StanzaNode? delete_node = event_node.get_subnode("delete", NS_URI_EVENT); + if (delete_node != null) { + string node = delete_node.get_attribute("node", NS_URI_EVENT); - if (retract_listeners.has_key(node)) { - retract_listeners[node].on_result(stream, message.from, id); + if (delete_listeners.has_key(node)) { + delete_listeners[node].on_result(stream, message.from); } } } @@ -264,4 +276,13 @@ namespace Xmpp.Xep.Pubsub { } } + public class DeleteListenerDelegate { + public delegate void ResultFunc(XmppStream stream, Jid jid); + public ResultFunc on_result { get; private owned set; } + + public DeleteListenerDelegate(owned ResultFunc on_result) { + this.on_result = (owned) on_result; + } + } + } diff --git a/xmpp-vala/src/module/xep/0084_user_avatars.vala b/xmpp-vala/src/module/xep/0084_user_avatars.vala index f3cd4060..4d84b34b 100644 --- a/xmpp-vala/src/module/xep/0084_user_avatars.vala +++ b/xmpp-vala/src/module/xep/0084_user_avatars.vala @@ -20,6 +20,11 @@ namespace Xmpp.Xep.UserAvatars { stream.get_module(Pubsub.Module.IDENTITY).publish.begin(stream, null, NS_URI_METADATA, sha1, metadata_node); } + public void unset_avatar(XmppStream stream) { + StanzaNode metadata_node = new StanzaNode.build("metadata", NS_URI_METADATA).add_self_xmlns(); + stream.get_module(Pubsub.Module.IDENTITY).delete_node(stream, null, NS_URI_METADATA); + } + public async Bytes? fetch_image(XmppStream stream, Jid jid, string hash) { Gee.List? items = yield stream.get_module(Pubsub.Module.IDENTITY).request_all(stream, jid, NS_URI_DATA); if (items == null || items.size == 0 || items[0].sub_nodes.size == 0) return null; @@ -41,23 +46,27 @@ namespace Xmpp.Xep.UserAvatars { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0084_user_avatars"); public signal void received_avatar_hash(XmppStream stream, Jid jid, string id); + public signal void avatar_removed(XmppStream stream, Jid jid); public override void attach(XmppStream stream) { - stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI_METADATA, true, on_pupsub_event, null); + stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI_METADATA, on_pupsub_item, null, on_pubsub_delete); } public override void detach(XmppStream stream) { stream.get_module(Pubsub.Module.IDENTITY).remove_filtered_notification(stream, NS_URI_METADATA); } - - public void on_pupsub_event(XmppStream stream, Jid jid, string hash, StanzaNode? node) { + public void on_pupsub_item(XmppStream stream, Jid jid, string hash, StanzaNode? node) { StanzaNode? info_node = node.get_subnode("info", NS_URI_METADATA); string? type = info_node == null ? null : info_node.get_attribute("type"); if (type != "image/png" && type != "image/jpeg") return; received_avatar_hash(stream, jid, hash); } + public void on_pubsub_delete(XmppStream stream, Jid jid) { + avatar_removed(stream, jid); + } + public override string get_ns() { return NS_URI; } public override string get_id() { return IDENTITY.id; } } diff --git a/xmpp-vala/src/module/xep/0402_bookmarks2.vala b/xmpp-vala/src/module/xep/0402_bookmarks2.vala index d1e53e6e..429f26f5 100644 --- a/xmpp-vala/src/module/xep/0402_bookmarks2.vala +++ b/xmpp-vala/src/module/xep/0402_bookmarks2.vala @@ -120,7 +120,7 @@ public class Module : BookmarksProvider, XmppStreamModule { } public override void attach(XmppStream stream) { - stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI, true, on_pupsub_item, on_pupsub_retract); + stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI, on_pupsub_item, on_pupsub_retract, null); } public override void detach(XmppStream stream) { -- cgit v1.2.3-54-g00ecf