diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index 6be49b9..77a72c8 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -48,7 +48,6 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
public HsNamedCaches NamedCaches { get; set; } = null!;
public GenericRoom GetRoom(string roomId) {
- if (roomId is null || !roomId.StartsWith("!")) throw new ArgumentException("Room ID must start with !", nameof(roomId));
return new GenericRoom(this, roomId);
}
@@ -186,6 +185,17 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
#endregion
+#region MSC 4133
+
+ public async Task UpdateProfilePropertyAsync(string name, object? value) {
+ var caps = await GetCapabilitiesAsync();
+ if(caps is null) throw new Exception("Failed to get capabilities");
+
+ }
+
+#endregion
+
+ [Obsolete("This method assumes no support for MSC 4069 and MSC 4133")]
public async Task UpdateProfileAsync(UserProfileResponse? newProfile, bool preserveCustomRoomProfile = true) {
if (newProfile is null) return;
Console.WriteLine($"Updating profile for {WhoAmI.UserId} to {newProfile.ToJson(ignoreNull: true)} (preserving room profiles: {preserveCustomRoomProfile})");
@@ -496,7 +506,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
catch (MatrixException e) {
if (e is not { ErrorCode: "M_UNRECOGNIZED" }) throw;
}
-
+
//fallback to legacy media
try {
var res = await ClientHttpClient.GetAsync($"/_matrix/media/v1/preview_url?url={HttpUtility.UrlEncode(url)}");
@@ -505,7 +515,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
catch (MatrixException e) {
if (e is not { ErrorCode: "M_UNRECOGNIZED" }) throw;
}
-
+
throw new LibMatrixException() {
ErrorCode = LibMatrixException.ErrorCodes.M_UNSUPPORTED,
Error = "Failed to download URL preview"
@@ -513,4 +523,8 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
}
#endregion
-}
\ No newline at end of file
+ private class CapabilitiesResponse {
+ [JsonPropertyName("capabilities")]
+ public Dictionary<string, object>? Capabilities { get; set; }
+ }
+}
diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs
index f9e3d04..adaac6d 100644
--- a/LibMatrix/Homeservers/RemoteHomeServer.cs
+++ b/LibMatrix/Homeservers/RemoteHomeServer.cs
@@ -55,6 +55,8 @@ public class RemoteHomeserver {
return data;
}
+
+ // TODO: Do we need to support retrieving individual profile properties? Is there any use for that besides just getting the full profile?
public async Task<ClientVersionsResponse> GetClientVersionsAsync() {
var resp = await ClientHttpClient.GetAsync($"/_matrix/client/versions");
diff --git a/LibMatrix/Responses/UserProfileResponse.cs b/LibMatrix/Responses/UserProfileResponse.cs
index 6c9380f..30e4c32 100644
--- a/LibMatrix/Responses/UserProfileResponse.cs
+++ b/LibMatrix/Responses/UserProfileResponse.cs
@@ -1,3 +1,4 @@
+using System.Text.Json;
using System.Text.Json.Serialization;
namespace LibMatrix.Responses;
@@ -8,4 +9,18 @@ public class UserProfileResponse {
[JsonPropertyName("displayname")]
public string? DisplayName { get; set; }
+
+ // MSC 4133 - Extending User Profile API with Key:Value pairs
+ [JsonExtensionData]
+ public Dictionary<string, JsonElement>? CustomKeys { get; set; }
+
+ public JsonElement? this[string key] {
+ get => CustomKeys?[key];
+ set {
+ if (value is null)
+ CustomKeys?.Remove(key);
+ else
+ (CustomKeys ??= [])[key] = value.Value;
+ }
+ }
}
\ No newline at end of file
|