From 80258a874ddfeb87b4b71f5791eab94a2465de6d Mon Sep 17 00:00:00 2001 From: fiaxh Date: Tue, 11 Oct 2022 13:37:48 +0200 Subject: Add support for reactions --- xmpp-vala/CMakeLists.txt | 2 + xmpp-vala/src/module/xep/0421_occupant_ids.vala | 45 +++++++++++++++ xmpp-vala/src/module/xep/0444_reactions.vala | 74 +++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 xmpp-vala/src/module/xep/0421_occupant_ids.vala create mode 100644 xmpp-vala/src/module/xep/0444_reactions.vala (limited to 'xmpp-vala') diff --git a/xmpp-vala/CMakeLists.txt b/xmpp-vala/CMakeLists.txt index 4ad7f0e9..de89f326 100644 --- a/xmpp-vala/CMakeLists.txt +++ b/xmpp-vala/CMakeLists.txt @@ -141,6 +141,8 @@ SOURCES "src/module/xep/0380_explicit_encryption.vala" "src/module/xep/0391_jingle_encrypted_transports.vala" "src/module/xep/0410_muc_self_ping.vala" + "src/module/xep/0421_occupant_ids.vala" + "src/module/xep/0444_reactions.vala" "src/module/xep/pixbuf_storage.vala" "src/util.vala" diff --git a/xmpp-vala/src/module/xep/0421_occupant_ids.vala b/xmpp-vala/src/module/xep/0421_occupant_ids.vala new file mode 100644 index 00000000..ce9f2471 --- /dev/null +++ b/xmpp-vala/src/module/xep/0421_occupant_ids.vala @@ -0,0 +1,45 @@ +namespace Xmpp.Xep.OccupantIds { + +public const string NS_URI = "urn:xmpp:occupant-id:0"; + +public static string? get_occupant_id(StanzaNode stanza) { + StanzaNode? node = stanza.get_subnode("occupant-id", NS_URI); + if (node == null) return null; + + return node.get_attribute("id"); +} + +public class Module : XmppStreamModule { + public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0421_occupant_ids"); + + public signal void received_occupant_id(XmppStream stream, Jid jid, string occupant_id); + public signal void received_own_occupant_id(XmppStream stream, Jid jid, string occupant_id); + + public override void attach(XmppStream stream) { + stream.get_module(Presence.Module.IDENTITY).received_available.connect(parse_occupant_id_from_presence); + } + + public override void detach(XmppStream stream) { + stream.get_module(Presence.Module.IDENTITY).received_available.disconnect(parse_occupant_id_from_presence); + } + + public override string get_ns() { return NS_URI; } + public override string get_id() { return IDENTITY.id; } + + public void parse_occupant_id_from_presence(XmppStream stream, Presence.Stanza presence) { + string? occupant_id = get_occupant_id(presence.stanza); + if (occupant_id == null) return; + + received_occupant_id(stream, presence.from, occupant_id); + + StanzaNode? x_node = presence.stanza.get_subnode("x", "http://jabber.org/protocol/muc#user"); + if (x_node == null) return; + foreach (StanzaNode status_node in x_node.get_subnodes("status", "http://jabber.org/protocol/muc#user")) { + if (int.parse(status_node.get_attribute("code")) == 110) { + received_own_occupant_id(stream, presence.from, occupant_id); + } + } + } +} + +} diff --git a/xmpp-vala/src/module/xep/0444_reactions.vala b/xmpp-vala/src/module/xep/0444_reactions.vala new file mode 100644 index 00000000..90d922d1 --- /dev/null +++ b/xmpp-vala/src/module/xep/0444_reactions.vala @@ -0,0 +1,74 @@ +using Gee; + +namespace Xmpp.Xep.Reactions { + +public const string NS_URI = "urn:xmpp:reactions:0"; + +public class Module : XmppStreamModule { + public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "reactions"); + + public signal void received_reactions(XmppStream stream, Jid from_jid, string message_id, Gee.List reactions, MessageStanza stanza); + + private ReceivedPipelineListener received_pipeline_listener = new ReceivedPipelineListener(); + + public void send_reaction(XmppStream stream, Jid jid, string stanza_type, string message_id, Gee.List reactions) { + StanzaNode reactions_node = new StanzaNode.build("reactions", NS_URI).add_self_xmlns(); + reactions_node.put_attribute("to", message_id); + foreach (string reaction in reactions) { + StanzaNode reaction_node = new StanzaNode.build("reaction", NS_URI); + reaction_node.put_node(new StanzaNode.text(reaction)); + reactions_node.put_node(reaction_node); + } + + MessageStanza message = new MessageStanza() { to=jid, type_=stanza_type }; + message.stanza.put_node(reactions_node); + + MessageProcessingHints.set_message_hint(message, MessageProcessingHints.HINT_STORE); + + stream.get_module(MessageModule.IDENTITY).send_message.begin(stream, message); + } + + public override void attach(XmppStream stream) { + stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI); + stream.get_module(MessageModule.IDENTITY).received_pipeline.connect(received_pipeline_listener); + } + + public override void detach(XmppStream stream) { + stream.get_module(ServiceDiscovery.Module.IDENTITY).remove_feature(stream, NS_URI); + stream.get_module(MessageModule.IDENTITY).received_pipeline.disconnect(received_pipeline_listener); + } + + public override string get_ns() { return NS_URI; } + public override string get_id() { return IDENTITY.id; } +} + +public class ReceivedPipelineListener : StanzaListener { + + private const string[] after_actions_const = {"EXTRACT_MESSAGE_2"}; + + public override string action_group { get { return ""; } } + public override string[] after_actions { get { return after_actions_const; } } + + public override async bool run(XmppStream stream, MessageStanza message) { + StanzaNode? reactions_node = message.stanza.get_subnode("reactions", NS_URI); + if (reactions_node == null) return false; + + string? to_attribute = reactions_node.get_attribute("to"); + if (to_attribute == null) return false; + + Gee.List reactions = new ArrayList(); + foreach (StanzaNode reaction_node in reactions_node.get_subnodes("reaction", NS_URI)) { + string? reaction = reaction_node.get_string_content(); + if (reaction == null) return false; + + if (!reactions.contains(reaction)) { + reactions.add(reaction); + } + } + stream.get_module(Module.IDENTITY).received_reactions(stream, message.from, to_attribute, reactions, message); + + return false; + } +} + +} -- cgit v1.2.3-70-g09d2