anotherim-desktop/xmpp-vala/src/module/xep/0402_bookmarks2.vala
2022-01-23 19:50:01 +01:00

137 lines
5.5 KiB
Vala

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);
if (items == null) return null;
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; }
}
}