git » sdk » commit bdcb9b8

Import roster items also

author Stephen Paul Weber
2026-06-30 19:50:11 UTC
committer Stephen Paul Weber
2026-06-30 19:50:11 UTC
parent 01b0656464135a84e83fd6b12f4456263bc1a139

Import roster items also

borogove/Chat.hx +6 -3
borogove/Client.hx +3 -0
borogove/Import.hx +19 -1
borogove/RosterItem.hx +27 -0
borogove/queries/RosterGet.hx +2 -8

diff --git a/borogove/Chat.hx b/borogove/Chat.hx
index 9e88d01..025f755 100644
--- a/borogove/Chat.hx
+++ b/borogove/Chat.hx
@@ -589,10 +589,10 @@ abstract class Chat extends EventEmitter {
 	}
 
 	@:allow(borogove)
-	private function updateFromRoster(item: { fn: Null<String>, subscription: String, groups: Array<String> }) {
+	private function updateFromRoster(item: RosterItem) {
 		isBookmarked = true;
 		setTrusted(item.subscription == "both" || item.subscription == "from");
-		if (item.fn != null && item.fn != "") displayName = item.fn;
+		if (item.name != null && item.name != "") displayName = item.name;
 		if (uiState == Invited) uiState = Open;
 		extensions.removeChildren("group", "jabber:iq:roster");
 		for (group in item.groups) {
@@ -2479,6 +2479,8 @@ class AvailableChat {
 	public final note: String;
 	@:allow(borogove)
 	private final caps: Caps;
+	@:allow(borogove)
+	private final rosterItem: Null<RosterItem>;
 
 	/**
 		Is this search result a channel?
@@ -2508,11 +2510,12 @@ class AvailableChat {
 	}
 
 	@:allow(borogove)
-	private function new(chatId: String, displayName: Null<String>, note: String, caps: Caps) {
+	private function new(chatId: String, displayName: Null<String>, note: String, caps: Caps, rosterItem: Null<RosterItem> = null) {
 		this.chatId = chatId;
 		this.displayName = displayName;
 		this.note = note;
 		this.caps = caps;
+		this.rosterItem = rosterItem;
 	}
 }
 
diff --git a/borogove/Client.hx b/borogove/Client.hx
index d4f9b3a..e070cfe 100644
--- a/borogove/Client.hx
+++ b/borogove/Client.hx
@@ -1227,6 +1227,9 @@ class Client extends EventEmitter {
 		} else {
 			getDirectChat(availableChat.chatId, false);
 		}
+		if (availableChat.rosterItem != null) {
+			chat.updateFromRoster(availableChat.rosterItem);
+		}
 		persistence.storeChats(accountId(), [chat]);
 		this.trigger("chats/update", [chat]);
 		return chat;
diff --git a/borogove/Import.hx b/borogove/Import.hx
index 93a336e..e05ed30 100644
--- a/borogove/Import.hx
+++ b/borogove/Import.hx
@@ -3,6 +3,8 @@ package borogove;
 import ltx.Sax;
 using StringTools;
 
+import borogove.Chat;
+
 @:expose
 @:access(Xml)
 class Import {
@@ -17,6 +19,7 @@ class Import {
 
 	public var onAccount: String->Void;
 	public var onChannel: String->Void;
+	public var onChat: (String, AvailableChat)->Void;
 	public var onMessage: (String, Message)->Void;
 
 	public function new(targetAccount: Null<String>, sortA: String = "Wt@|q", sortB: String = "a ") {
@@ -30,6 +33,7 @@ class Import {
 		var item = null;
 		var mucComponent = false;
 		var inArchive = false;
+		var inRoster = false;
 		var resultStanza: Null<Stanza> = null;
 		p.onStartElement = (tag: Xml) -> {
 			ns = NsContext.from(ns, tag);
@@ -53,7 +57,15 @@ class Import {
 				sortA = sortAinit;
 				item = tag.get("name");
 				if (mucComponent && onChannel != null) onChannel(item + "@" + host);
+			case "{jabber:iq:roster}query":
+				if (inArchive) throw "Roster inside an archive?";
+				inRoster = true;
+			case "{jabber:iq:roster}item":
+				if (inRoster && onChat != null && !ignoredSources[item + "@" + host]) {
+					resultStanza = new Stanza("item", tag.attributeMap);
+				}
 			case "{urn:xmpp:pie:0#mam}archive":
+				if (inRoster) throw "Archive inside a roster?";
 				if (item != null && host != null) inArchive = true;
 			case "{urn:xmpp:mam:2}result":
 				if (inArchive && onMessage != null && !ignoredSources[item + "@" + host]) {
@@ -65,7 +77,11 @@ class Import {
 			if (resultStanza != null) {
 				resultStanza.up();
 				if (resultStanza.atTop()) {
-					if (onMessage != null) processResultStanza(resultStanza, item, host);
+					if (inRoster) {
+						if (onChat != null) onChat(item + "@" + host, new AvailableChat(resultStanza.attr.get("jid"), resultStanza.attr.get("name"), "Import", CapsRepo.empty, resultStanza));
+					} else if (inArchive) {
+						if (onMessage != null) processResultStanza(resultStanza, item, host);
+					}
 					resultStanza = null;
 				}
 				return;
@@ -79,6 +95,8 @@ class Import {
 				mucComponent = false;
 			case "{urn:xmpp:pie:0#component}item", "{urn:xmpp:pie:0}user":
 				item = null;
+			case "{jabber:iq:roster}query":
+				inRoster = false;
 			case "{urn:xmpp:pie:0#mam}archive":
 				inArchive = false;
 			case "{urn:xmpp:mam:2}result":
diff --git a/borogove/RosterItem.hx b/borogove/RosterItem.hx
new file mode 100644
index 0000000..5b4802a
--- /dev/null
+++ b/borogove/RosterItem.hx
@@ -0,0 +1,27 @@
+package borogove;
+
+@:nullSafety(StrictThreaded)
+@:forward(toString)
+abstract RosterItem(Stanza) from Stanza to Stanza {
+	public var jid(get, never): Null<String>;
+	public var name(get, never): Null<String>;
+	public var subscription(get, never): Null<String>;
+	public var groups(get, never): Array<String>;
+
+	private inline function get_jid() {
+		return this.attr.get("jid");
+	}
+
+	private inline function get_name() {
+		return this.attr.get("name");
+	}
+
+	private inline function get_subscription() {
+		return this.attr.get("subscription");
+	}
+
+	private inline function get_groups() {
+		// TODO: cannot specify namespace here due to bugs in namespace handling in allTags
+		return this.allTags("group").map(g -> g.getText());
+	}
+}
diff --git a/borogove/queries/RosterGet.hx b/borogove/queries/RosterGet.hx
index ee0a554..2e7f66f 100644
--- a/borogove/queries/RosterGet.hx
+++ b/borogove/queries/RosterGet.hx
@@ -14,7 +14,7 @@ class RosterGet extends GenericQuery {
 	public var queryId:String = null;
 	public var ver:String = null;
 	private var responseStanza:Stanza;
-	private var result: Array<{ jid: String, fn: String, subscription: String, groups: Array<String> }>;
+	private var result: Array<RosterItem>;
 
 	public function new(?ver: String) {
 		var attr: DynamicAccess<String> = { xmlns: xmlns };
@@ -41,13 +41,7 @@ class RosterGet extends GenericQuery {
 				return [];
 			}
 			ver = q.attr.get("ver");
-			// TODO: cannot specify namespace here due to bugs in namespace handling in allTags
-			result = q.allTags("item").map((item) -> {
-				jid: item.attr.get("jid"),
-				fn: item.attr.get("name"),
-				subscription: item.attr.get("subscription"),
-				groups: item.allTags("group").map(g -> g.getText())
-			});
+			result = q.allTags("item");
 		}
 		return result;
 	}