aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala/src/module/xep/0490_message_displayed_synchronization.vala
diff options
context:
space:
mode:
Diffstat (limited to 'xmpp-vala/src/module/xep/0490_message_displayed_synchronization.vala')
-rw-r--r--xmpp-vala/src/module/xep/0490_message_displayed_synchronization.vala92
1 files changed, 92 insertions, 0 deletions
diff --git a/xmpp-vala/src/module/xep/0490_message_displayed_synchronization.vala b/xmpp-vala/src/module/xep/0490_message_displayed_synchronization.vala
new file mode 100644
index 00000000..38437735
--- /dev/null
+++ b/xmpp-vala/src/module/xep/0490_message_displayed_synchronization.vala
@@ -0,0 +1,92 @@
+using Gee;
+namespace Xmpp.Xep.MessageDisplayedSynchronization {
+ public const string NS_URI = "urn:xmpp:mds:displayed:0";
+ public const string NS_URI_SERVER_ASSIST = "urn:xmpp:mds:server-assist:0";
+
+ public class Module : XmppStreamModule {
+ public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0490_message_displayed_synchronization");
+
+ public signal void on_message_displayed(Jid conversation_jid, Jid stanza_id_by_jid, string stanza_id);
+
+ private void handle_displayed_node_item(XmppStream stream, string? id, StanzaNode? item) {
+ if (id == null || item == null) return;
+ Jid conversation_jid = Jid.from_string(id);
+ StanzaNode? stanza_id_node = item.get_subnode("stanza-id", UniqueStableStanzaIDs.NS_URI);
+ if (stanza_id_node == null || stanza_id_node.get_attribute("by") == null || stanza_id_node.get_attribute("id") == null) return;
+ Jid stanza_id_by_jid = Jid.from_string(stanza_id_node.get_attribute("by"));
+ string stanza_id = stanza_id_node.get_attribute("id");
+ if (stream.has_flag(Flag.IDENTITY)) {
+ stream.get_flag(Flag.IDENTITY).learn_mds(conversation_jid, stanza_id_by_jid, stanza_id);
+ }
+ on_message_displayed(conversation_jid, stanza_id_by_jid, stanza_id);
+ }
+
+ private void on_pubsub_item(XmppStream stream, Jid jid, string id, StanzaNode? item) {
+ if (!jid.equals(stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid)) {
+ warning("Received alleged mds item from %s, ignoring", jid.to_string());
+ return;
+ }
+ handle_displayed_node_item(stream, id, item);
+ }
+
+ private void on_initial_presence_sent(XmppStream stream) {
+ var pubsub = stream.get_module(Pubsub.Module.IDENTITY);
+ pubsub.request_all.begin(stream, null, NS_URI, (_, res) => {
+ Gee.List<StanzaNode>? items = pubsub.request_all.end(res);
+ foreach (StanzaNode node_item in items) {
+ handle_displayed_node_item(stream, node_item.get_attribute("id"), node_item.get_subnode("displayed", NS_URI));
+ }
+ });
+ }
+
+ public async bool update_message_displayed(XmppStream stream, Jid conversation_jid, Jid stanza_id_by_jid, string stanza_id) {
+ var pubsub = stream.get_module(Pubsub.Module.IDENTITY);
+ var node = new StanzaNode.build("displayed", NS_URI).add_self_xmlns()
+ .put_node(new StanzaNode.build("stanza-id", UniqueStableStanzaIDs.NS_URI).add_self_xmlns()
+ .put_attribute("by", stanza_id_by_jid.to_string())
+ .put_attribute("id", stanza_id));
+ var options = new Pubsub.PublishOptions()
+ .set_persist_items(true)
+ .set_max_items("max")
+ .set_send_last_published_item("never")
+ .set_access_model("whitelist");
+ return yield pubsub.publish(stream, stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid, NS_URI, conversation_jid.to_string(), node, options);
+ }
+
+ public override void attach(XmppStream stream) {
+ stream.get_module(Pubsub.Module.IDENTITY).add_filtered_notification(stream, NS_URI, on_pubsub_item, null, null);
+ stream.get_module(Presence.Module.IDENTITY).initial_presence_sent.connect(on_initial_presence_sent);
+ if (!stream.has_flag(Flag.IDENTITY)) {
+ stream.add_flag(new Flag());
+ }
+ }
+
+ public override void detach(XmppStream stream) {
+ stream.get_module(Presence.Module.IDENTITY).initial_presence_sent.disconnect(on_initial_presence_sent);
+ stream.get_module(Pubsub.Module.IDENTITY).remove_filtered_notification(stream, NS_URI);
+ }
+
+ public override string get_ns() { return NS_URI; }
+ public override string get_id() { return IDENTITY.id; }
+
+ }
+
+ public class Flag : XmppStreamFlag {
+ public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "mds");
+
+ private Map<Jid, Jid> stanza_id_bys = new HashMap<Jid, Jid>(Jid.hash_func, Jid.equals_func);
+ private Map<Jid, string> stanza_ids = new HashMap<Jid, string>(Jid.hash_func, Jid.equals_func);
+
+ public void learn_mds(Jid jid, Jid stanza_by, string stanza_id) {
+ stanza_id_bys[jid] = stanza_by;
+ stanza_ids[jid] = stanza_id;
+ }
+
+ public bool is_displayed(Jid conversation_jid, Jid stanza_by, string stanza_id) {
+ return stanza_id_bys[conversation_jid].equals(stanza_by) && stanza_ids[conversation_jid] == stanza_id;
+ }
+
+ public override string get_ns() { return NS_URI; }
+ public override string get_id() { return IDENTITY.id; }
+ }
+} \ No newline at end of file