git » sdk » main » tree

[main] / borogove / Member.hx

package borogove;

import thenshim.Promise;
import haxe.ds.ReadOnlyArray;

import borogove.Chat;
import borogove.Presence;
import borogove.queries.PubsubGet;

#if cpp
import HaxeCBridge;
#end

@:expose
@:nullSafety(Strict)
#if cpp
@:build(HaxeCBridge.expose())
@:build(HaxeSwiftBridge.expose())
#end
class Member {
	/**
		A unique id for this member
	**/
	public final id: String;

	/**
		Display name to show for this member
	**/
	public final displayName: String;

	/**
		Avatar URI for this member, or null when none is known
	**/
	public final photoUri: Null<String>;

	/**
		Fallback avatar URI to use when no photo is available
	**/
	public final placeholderUri: String;

	/**
		True when this member is the connected account
	**/
	public final isSelf: Bool;

	/**
		Chat metadata for this member when it is available as a direct Chat
	**/
	public final chat: Null<AvailableChat>;

	/**
		Roles this member has in the Chat
	**/
	public final roles: ReadOnlyArray<Role>;

	public final showPresence: ShowPresence;

	@:allow(borogove)
	private var presence: Map<String, Presence>;

	@:allow(borogove)
	private final jid: JID;

	@:allow(borogove)
	private function new(id: String, displayName: String, photoUri: Null<String>, isSelf: Bool, roles: Array<Role>, jid: JID, presence: Map<String, Presence>, chat: Null<AvailableChat>) {
		this.id = id;
		this.displayName = displayName;
		this.photoUri = photoUri;
		this.placeholderUri = Color.defaultPhoto(id, displayName.charAt(0).toUpperCase());
		this.isSelf = isSelf;
		this.roles = roles;
		this.jid = jid;
		this.presence = presence;
		this.chat = chat;
		var lowestShow = Offline;
		var highestPrio = -100000;
		for (_ => p in presence) {
			if (p.priority >= highestPrio) {
				highestPrio = p.priority;
				if ((lowestShow : Int) > (p.show : Int)) lowestShow = p.show;
			}
		}
		showPresence = lowestShow;
	}

	/**
		Load the member's profile

		@param client connected client used to send the profile query
		@returns Promise resolving to the member Profile
	**/
	public function profile(client: Client): Promise<Profile> {
		return new Promise((resolve, reject) -> {
			final get = new PubsubGet(jid.asString(), "urn:xmpp:vcard4");
			get.onFinished(() -> {
				final item = get.getResult()[0];
				final fromItem = item?.getChild("vcard", "urn:ietf:params:xml:ns:vcard-4.0");
				final vcard = fromItem == null ? new Stanza("vcard", { xmlns: "urn:ietf:params:xml:ns:vcard-4.0" }) : fromItem;
				if (!vcard.hasChild("fn")) {
					vcard.insertChild(0, new Stanza("fn").textTag("text", displayName));
				}
				resolve(new Profile(vcard));
			});
			client.sendQuery(get);
		});
	}

	/**
		Load the member's status

		@param client connected client used to send the profile query
		@returns Promise resolving to the member Status
	**/
	public function status(client: Client): Promise<Status> {
		return new Promise((resolve, reject) -> {
			final get = new PubsubGet(jid.asString(), "http://jabber.org/protocol/activity");
			get.onFinished(() -> {
				final item = get.getResult()[0];

				final activity = item?.getChild("activity", "http://jabber.org/protocol/activity");
				resolve(new Status(activity?.getChild("undefined")?.getChildText("emoji", "https://ns.borogove.dev/") ?? "", activity?.getChildText("text") ?? ""));
			});
			client.sendQuery(get);
		});
	}
}