aboutsummaryrefslogtreecommitdiff
path: root/xmpp-vala/src/module/xep/0402_bookmarks2.vala
blob: cafe143587904aac24b1486b2c2037a21467ab88 (plain) (blame)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using Gee;

namespace Xmpp.Xep.Bookmarks2 {

public const string NS_URI = "urn:xmpp:bookmarks:1";
public const string NS_URI_COMPAT = NS_URI + "#compat";

public class Module : BookmarksProvider, XmppStreamModule {
    public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0402_bookmarks2");

    public async Set<Conference>? get_conferences(XmppStream stream) {
        HashMap<Jid, Conference>? hm = null;

        Flag? flag = stream.get_flag(Flag.IDENTITY);
        if (flag != null) {
            hm = flag.conferences;
        } else {
            Gee.List<StanzaNode>? items = yield stream.get_module(Pubsub.Module.IDENTITY).request_all(stream, stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid, NS_URI);

            hm = new HashMap<Jid, Conference>(Jid.hash_func, Jid.equals_func);
            foreach (StanzaNode item_node in items) {
                Conference? conference = parse_item_node(item_node.sub_nodes[0], item_node.get_attribute("id"));
                if (conference == null) continue;
                hm[conference.jid] = conference;
            }
            stream.add_flag(new Flag(hm));
        }


        var ret = new HashSet<Conference>();
        foreach (var conference in hm.values) {
            ret.add(conference);
        }
        return ret;
    }

    public async void add_conference(XmppStream stream, Conference conference) {
        StanzaNode conference_node = new StanzaNode.build("conference", NS_URI).add_self_xmlns()
            .put_attribute("autojoin", conference.autojoin.to_string());
        if (conference.name != null) {
            conference_node.put_attribute("name", conference.name);
        }
        if (conference.nick != null) {
            conference_node.put_node((new StanzaNode.build("nick", NS_URI)).put_node(new StanzaNode.text(conference.nick)));
        }
        if (conference.password != null) {
            conference_node.put_node((new StanzaNode.build("password", NS_URI)).put_node(new StanzaNode.text(conference.password)));
        }
        var publish_options = new Pubsub.PublishOptions()
                .set_persist_items(true)
                .set_max_items("max")
                .set_send_last_published_item("never")
                .set_access_model("whitelist");

        yield stream.get_module(Pubsub.Module.IDENTITY).publish(stream, stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid, NS_URI, conference.jid.to_string(), conference_node, publish_options);
    }

    public async void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference) {
        yield add_conference(stream, modified_conference);
    }

    public async void remove_conference(XmppStream stream, Conference conference) {
        yield stream.get_module(Pubsub.Module.IDENTITY).retract_item(stream,
                    stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid,
                    NS_URI,
                    conference.jid.to_string());
    }

    private void on_pupsub_item(XmppStream stream, Jid jid, string id, StanzaNode? node) {
        Conference conference = parse_item_node(node, id);
        Flag? flag = stream.get_flag(Flag.IDENTITY);
        if (flag != null) {
            flag.conferences[conference.jid] = conference;
        }
        conference_added(stream, conference);
    }

    private void on_pupsub_retract(XmppStream stream, Jid jid, string id) {
        try {
            Jid jid_parsed = new Jid(id);
            Flag? flag = stream.get_flag(Flag.IDENTITY);
            if (flag != null) {
                flag.conferences.unset(jid_parsed);
            }
            conference_removed(stream, jid_parsed);
        } catch (InvalidJidError e) {
            warning("Ignoring conference bookmark update with invalid Jid: %s", e.message);
        }
    }

    private Conference? parse_item_node(StanzaNode conference_node, string id) {
        Conference conference = new Conference();
        try {
            Jid jid_parsed = new Jid(id);
            if (jid_parsed.resourcepart != null) return null;
            conference.jid = jid_parsed;
        } catch (InvalidJidError e) {
            warning("Ignoring conference bookmark update with invalid Jid: %s", e.message);
            return null;
        }

        if (conference_node.name != "conference" || conference_node.ns_uri != NS_URI) return null;

        conference.name = conference_node.get_attribute("name", NS_URI);
        conference.autojoin = conference_node.get_attribute_bool("autojoin", false, NS_URI);
        conference.nick = conference_node.get_deep_string_content("nick");
        return conference;
    }

    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);
    }

    public override void detach(XmppStream stream) {
        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, "bookmarks2");

    public Flag(HashMap<Jid, Conference> conferences) {
        this.conferences = conferences;
    }

    public HashMap<Jid, Conference> conferences = new HashMap<Jid, Conference>(Jid.hash_func, Jid.equals_func);

    public override string get_ns() { return NS_URI; }
    public override string get_id() { return IDENTITY.id; }
}

}