git » sdk » commit d62d240

Get MUC channel avatars

author Stephen Paul Weber
2023-11-09 05:39:04 UTC
committer Stephen Paul Weber
2023-11-09 05:39:04 UTC
parent 405302bf9ac7ab48de0d643136d591b1113aea63

Get MUC channel avatars

xmpp/Chat.hx +11 -15
xmpp/Client.hx +26 -1
xmpp/queries/VcardTempGet.hx +52 -0

diff --git a/xmpp/Chat.hx b/xmpp/Chat.hx
index 71f02f7..c70009f 100644
--- a/xmpp/Chat.hx
+++ b/xmpp/Chat.hx
@@ -75,7 +75,17 @@ abstract class Chat {
 	}
 
 	public function getPhoto(callback:(String)->Void) {
-		callback(Color.defaultPhoto(chatId, getDisplayName().charAt(0)));
+		if (avatarSha1 != null) {
+			persistence.getMediaUri("sha-1", avatarSha1, (uri) -> {
+				if (uri != null) {
+					callback(uri);
+				} else {
+					callback(Color.defaultPhoto(chatId, getDisplayName().charAt(0)));
+				}
+			});
+		} else {
+			callback(Color.defaultPhoto(chatId, getDisplayName().charAt(0)));
+		}
 	}
 
 	public function readUpTo() {
@@ -333,20 +343,6 @@ class DirectChat extends Chat {
 		persistence.storeChat(client.accountId(), this);
 		client.trigger("chats/update", [this]);
 	}
-
-	override public function getPhoto(callback:(String)->Void) {
-		if (avatarSha1 != null) {
-			persistence.getMediaUri("sha-1", avatarSha1, (uri) -> {
-				if (uri != null) {
-					callback(uri);
-				} else {
-					callback(Color.defaultPhoto(chatId, getDisplayName().charAt(0)));
-				}
-			});
-		} else {
-			super.getPhoto(callback);
-		}
-	}
 }
 
 @:expose
diff --git a/xmpp/Client.hx b/xmpp/Client.hx
index 09b6e98..a56c89d 100644
--- a/xmpp/Client.hx
+++ b/xmpp/Client.hx
@@ -18,6 +18,7 @@ import xmpp.queries.JabberIqGatewayGet;
 import xmpp.queries.PubsubGet;
 import xmpp.queries.Push2Enable;
 import xmpp.queries.RosterGet;
+import xmpp.queries.VcardTempGet;
 using Lambda;
 
 @:expose
@@ -249,7 +250,8 @@ class Client extends xmpp.EventEmitter {
 			final stanza:Stanza = event.stanza;
 			final c = stanza.getChild("c", "http://jabber.org/protocol/caps");
 			if (stanza.attr.get("from") != null && stanza.attr.get("type") == null) {
-				final chat = getChat(JID.parse(stanza.attr.get("from")).asBare().asString());
+				final from = JID.parse(stanza.attr.get("from"));
+				final chat = getChat(from.asBare().asString());
 				if (chat == null) {
 					trace("Presence for unknown JID: " + stanza.attr.get("from"));
 					return EventUnhandled;
@@ -276,6 +278,29 @@ class Client extends xmpp.EventEmitter {
 						}
 					});
 				}
+				if (from.isBare()) {
+					final avatarSha1Hex = stanza.findText("{vcard-temp:x:update}x/photo#");
+					if (avatarSha1Hex != null) {
+						final avatarSha1 = Bytes.ofHex(avatarSha1Hex).getData();
+						chat.setAvatarSha1(avatarSha1);
+						persistence.storeChat(accountId(), chat);
+						persistence.getMediaUri("sha-1", avatarSha1, (uri) -> {
+							if (uri == null) {
+								final vcardGet = new VcardTempGet(from);
+								vcardGet.onFinished(() -> {
+									final vcard = vcardGet.getResult();
+									if (vcard.photo == null) return;
+									persistence.storeMedia(vcard.photo.mime, vcard.photo.data.getData(), () -> {
+										this.trigger("chats/update", [chat]);
+									});
+								});
+								sendQuery(vcardGet);
+							} else {
+								this.trigger("chats/update", [chat]);
+							}
+						});
+					}
+				}
 				return EventHandled;
 			}
 
diff --git a/xmpp/queries/VcardTempGet.hx b/xmpp/queries/VcardTempGet.hx
new file mode 100644
index 0000000..ed8df0c
--- /dev/null
+++ b/xmpp/queries/VcardTempGet.hx
@@ -0,0 +1,52 @@
+package xmpp.queries;
+
+import haxe.DynamicAccess;
+import haxe.Exception;
+import haxe.crypto.Base64;
+import haxe.io.Bytes;
+
+import xmpp.ID;
+import xmpp.ResultSet;
+import xmpp.Stanza;
+import xmpp.Stream;
+import xmpp.queries.GenericQuery;
+
+class VcardTempGet extends GenericQuery {
+	public var xmlns(default, null) = "vcard-temp";
+	public var queryId:String = null;
+	public var ver:String = null;
+	private var responseStanza:Stanza;
+	private var result: {photo:Null<{mime:String, data:Bytes}>};
+
+	public function new(to: JID) {
+		/* Build basic query */
+		queryId = ID.short();
+		queryStanza = new Stanza("iq", { to: to.asString(), type: "get", id: queryId });
+		queryStanza.tag("vCard", { xmlns: xmlns }).up();
+	}
+
+	public function handleResponse(stanza:Stanza) {
+		responseStanza = stanza;
+		finish();
+	}
+
+	public function getResult() {
+		if (responseStanza == null) {
+			return {photo: null};
+		}
+		if(result == null) {
+			final vcard = responseStanza.getChild("vCard", xmlns);
+			if(vcard == null) {
+				return {photo: null};
+			}
+			final photoMime = vcard.findText("PHOTO/TYPE#");
+			final photoBinval = vcard.findText("PHOTO/BINVAL#");
+			if (photoMime != null && photoBinval != null) {
+				result = {photo: { mime: photoMime, data: Base64.decode(StringTools.replace(photoBinval, "\n", "")) } };
+			} else {
+				result = {photo: null};
+			}
+		}
+		return result;
+	}
+}