git » sdk » main » tree

[main] / borogove / Presence.hx

package borogove;

import borogove.Hash;
import borogove.MucUser;
import borogove.Role;

enum abstract ShowPresence(Int) to Int {
	var Online;
	var Idle;
	var DoNotDisturb;
	var Standby;
	var Offline;
}

@:nullSafety(StrictThreaded)
@:forward(toString)
@:expose
abstract Presence(Stanza) from Stanza to Stanza {
	public var capsNode(get, never): Null<String>;
	public var ver(get, never): Null<String>;
	public var mucUser(get, never): Null<MucUser>;
	public var hats(get, never): Null<Array<Role>>;
	public var avatarHash(get, never): Null<Hash>;
	public var type(get, never): Null<String>;
	public var show(get, never): ShowPresence;
	public var priority(get, never): Int;

	/**
		Create a presence stanza wrapper from caps, MUC metadata, and avatar hash.
	**/
	public function new(caps: Null<Caps>, mucUser: Null<MucUser>, avatarHash: Null<Hash>): Presence {
		final stanza = new Stanza("presence", { xmlns: "jabber:client" });
		if (caps != null) caps.addC(stanza);
		if (mucUser != null) stanza.addChild(mucUser);
		if (avatarHash != null) {
			stanza.tag("x", { xmlns: "vcard-temp:x:update" }).textTag("photo", avatarHash.toHex()).up();
		}

		this = stanza;
	}

	private inline function get_capsNode() {
		final c = this.getChild("c", "http://jabber.org/protocol/caps");
		return c?.attr?.get("node");
	}

	private inline function get_ver() {
		final c = this.getChild("c", "http://jabber.org/protocol/caps");
		return c?.attr?.get("ver");
	}

	private inline function get_mucUser() {
		return this.getChild("x", "http://jabber.org/protocol/muc#user");
	}

	private inline function get_hats() {
		return (this.getChild("hats", "urn:xmpp:hats:0")?.allTags("hat") ?? []).map(hat -> new Role(hat.attr.get("uri") ?? "", hat.attr.get("title") ?? ""));
	}

	private inline function get_avatarHash() {
		final avatarSha1Hex = this.findText("{vcard-temp:x:update}x/photo#");
		return avatarSha1Hex == null || avatarSha1Hex == "" ? null : Hash.fromHex("sha-1", avatarSha1Hex);
	}

	private inline function get_type() {
		return this.attr.get("type");
	}

	private inline function get_show() {
		if (type == "unavailable") return Offline;

		return switch (this.getChildText("show")) {
			case "away": Idle;
			case "dnd": DoNotDisturb;
			case "xa": Standby;
			default: Online;
		};
	}

	private inline function get_priority() {
		return Std.parseInt(this.getChildText("priority") ?? "0") ?? 0;
	}
}