1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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; }
}
}
|