From 6975119b7d21cafdd0620d35b9542fb5d47ef392 Mon Sep 17 00:00:00 2001 From: Rory& Date: Fri, 20 Jun 2025 04:50:00 +0200 Subject: Basic federation, move some response classes to the right namespace --- LibMatrix/EventIdResponse.cs | 8 --- LibMatrix/Extensions/CanonicalJsonSerializer.cs | 9 ++++ LibMatrix/Homeservers/FederationClient.cs | 65 +++++++++++++++++++++++++ LibMatrix/MessagesResponse.cs | 17 ------- LibMatrix/Responses/EventIdResponse.cs | 8 +++ LibMatrix/Responses/MessagesResponse.cs | 17 +++++++ LibMatrix/Responses/UserIdAndReason.cs | 11 +++++ LibMatrix/Responses/WhoAmIResponse.cs | 14 ++++++ LibMatrix/RoomTypes/GenericRoom.cs | 2 +- LibMatrix/RoomTypes/SpaceRoom.cs | 1 + LibMatrix/UserIdAndReason.cs | 11 ----- LibMatrix/WhoAmIResponse.cs | 14 ------ 12 files changed, 126 insertions(+), 51 deletions(-) delete mode 100644 LibMatrix/EventIdResponse.cs delete mode 100644 LibMatrix/MessagesResponse.cs create mode 100644 LibMatrix/Responses/EventIdResponse.cs create mode 100644 LibMatrix/Responses/MessagesResponse.cs create mode 100644 LibMatrix/Responses/UserIdAndReason.cs create mode 100644 LibMatrix/Responses/WhoAmIResponse.cs delete mode 100644 LibMatrix/UserIdAndReason.cs delete mode 100644 LibMatrix/WhoAmIResponse.cs (limited to 'LibMatrix') diff --git a/LibMatrix/EventIdResponse.cs b/LibMatrix/EventIdResponse.cs deleted file mode 100644 index 6a04229..0000000 --- a/LibMatrix/EventIdResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Text.Json.Serialization; - -namespace LibMatrix; - -public class EventIdResponse { - [JsonPropertyName("event_id")] - public required string EventId { get; set; } -} \ No newline at end of file diff --git a/LibMatrix/Extensions/CanonicalJsonSerializer.cs b/LibMatrix/Extensions/CanonicalJsonSerializer.cs index 55a4b1a..ae535aa 100644 --- a/LibMatrix/Extensions/CanonicalJsonSerializer.cs +++ b/LibMatrix/Extensions/CanonicalJsonSerializer.cs @@ -1,6 +1,7 @@ using System.Collections.Frozen; using System.Reflection; using System.Text.Json; +using System.Text.Json.Nodes; using System.Text.Json.Serialization.Metadata; using ArcaneLibs.Extensions; @@ -57,6 +58,14 @@ public static class CanonicalJsonSerializer { // public static String Serialize(TValue value, JsonTypeInfo jsonTypeInfo) => JsonSerializer.Serialize(value, jsonTypeInfo, _options); // public static String Serialize(Object value, JsonTypeInfo jsonTypeInfo) + public static byte[] SerializeToUtf8Bytes(T value, JsonSerializerOptions? options = null) { + var newOptions = MergeOptions(null); + return JsonSerializer.SerializeToNode(value, options) // We want to allow passing custom converters for eg. double/float -> string here... + .SortProperties()! + .CanonicalizeNumbers()! + .ToJsonString(newOptions).AsBytes().ToArray(); + } + #endregion // ReSharper disable once UnusedType.Local diff --git a/LibMatrix/Homeservers/FederationClient.cs b/LibMatrix/Homeservers/FederationClient.cs index 617b737..a2cb12d 100644 --- a/LibMatrix/Homeservers/FederationClient.cs +++ b/LibMatrix/Homeservers/FederationClient.cs @@ -1,6 +1,7 @@ using System.Text.Json.Serialization; using LibMatrix.Extensions; using LibMatrix.Services; +using Microsoft.VisualBasic.CompilerServices; namespace LibMatrix.Homeservers; @@ -17,6 +18,70 @@ public class FederationClient { public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } public async Task GetServerVersionAsync() => await HttpClient.GetFromJsonAsync("/_matrix/federation/v1/version"); + public async Task GetServerKeysAsync() => await HttpClient.GetFromJsonAsync("/_matrix/key/v2/server"); +} + +public class ServerKeysResponse { + [JsonPropertyName("server_name")] + public string ServerName { get; set; } + + [JsonPropertyName("valid_until_ts")] + public ulong ValidUntilTs { get; set; } + + [JsonIgnore] + public DateTime ValidUntil { + get => DateTimeOffset.FromUnixTimeMilliseconds((long)ValidUntilTs).DateTime; + set => ValidUntilTs = (ulong)new DateTimeOffset(value).ToUnixTimeMilliseconds(); + } + + [JsonPropertyName("verify_keys")] + public Dictionary VerifyKeys { get; set; } = new(); + + [JsonIgnore] + public Dictionary VerifyKeysById { + get => VerifyKeys.ToDictionary(key => (VersionedKeyId)key.Key, key => key.Value); + set => VerifyKeys = value.ToDictionary(key => (string)key.Key, key => key.Value); + } + + [JsonPropertyName("old_verify_keys")] + public Dictionary OldVerifyKeys { get; set; } = new(); + + [JsonIgnore] + public Dictionary OldVerifyKeysById { + get => OldVerifyKeys.ToDictionary(key => (VersionedKeyId)key.Key, key => key.Value); + set => OldVerifyKeys = value.ToDictionary(key => (string)key.Key, key => key.Value); + } + + public class VersionedKeyId { + public required string Algorithm { get; set; } + public required string KeyId { get; set; } + + public static implicit operator VersionedKeyId(string key) { + var parts = key.Split(':', 2); + if (parts.Length != 2) throw new ArgumentException("Invalid key format. Expected 'algorithm:keyId'.", nameof(key)); + return new VersionedKeyId { Algorithm = parts[0], KeyId = parts[1] }; + } + + public static implicit operator string(VersionedKeyId key) => $"{key.Algorithm}:{key.KeyId}"; + public static implicit operator (string, string)(VersionedKeyId key) => (key.Algorithm, key.KeyId); + public static implicit operator VersionedKeyId((string algorithm, string keyId) key) => (key.algorithm, key.keyId); + } + + public class CurrentVerifyKey { + [JsonPropertyName("key")] + public string Key { get; set; } + } + + public class ExpiredVerifyKey : CurrentVerifyKey { + [JsonPropertyName("expired_ts")] + public ulong ExpiredTs { get; set; } + + [JsonIgnore] + public DateTime Expired { + get => DateTimeOffset.FromUnixTimeMilliseconds((long)ExpiredTs).DateTime; + set => ExpiredTs = (ulong)new DateTimeOffset(value).ToUnixTimeMilliseconds(); + } + } } public class ServerVersionResponse { diff --git a/LibMatrix/MessagesResponse.cs b/LibMatrix/MessagesResponse.cs deleted file mode 100644 index 526da74..0000000 --- a/LibMatrix/MessagesResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Text.Json.Serialization; - -namespace LibMatrix; - -public class MessagesResponse { - [JsonPropertyName("start")] - public string Start { get; set; } - - [JsonPropertyName("end")] - public string? End { get; set; } - - [JsonPropertyName("chunk")] - public List Chunk { get; set; } = new(); - - [JsonPropertyName("state")] - public List State { get; set; } = new(); -} \ No newline at end of file diff --git a/LibMatrix/Responses/EventIdResponse.cs b/LibMatrix/Responses/EventIdResponse.cs new file mode 100644 index 0000000..9e23210 --- /dev/null +++ b/LibMatrix/Responses/EventIdResponse.cs @@ -0,0 +1,8 @@ +using System.Text.Json.Serialization; + +namespace LibMatrix.Responses; + +public class EventIdResponse { + [JsonPropertyName("event_id")] + public required string EventId { get; set; } +} \ No newline at end of file diff --git a/LibMatrix/Responses/MessagesResponse.cs b/LibMatrix/Responses/MessagesResponse.cs new file mode 100644 index 0000000..4912add --- /dev/null +++ b/LibMatrix/Responses/MessagesResponse.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; + +namespace LibMatrix.Responses; + +public class MessagesResponse { + [JsonPropertyName("start")] + public string Start { get; set; } + + [JsonPropertyName("end")] + public string? End { get; set; } + + [JsonPropertyName("chunk")] + public List Chunk { get; set; } = new(); + + [JsonPropertyName("state")] + public List State { get; set; } = new(); +} \ No newline at end of file diff --git a/LibMatrix/Responses/UserIdAndReason.cs b/LibMatrix/Responses/UserIdAndReason.cs new file mode 100644 index 0000000..176cf7c --- /dev/null +++ b/LibMatrix/Responses/UserIdAndReason.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; + +namespace LibMatrix.Responses; + +internal class UserIdAndReason(string userId = null!, string reason = null!) { + [JsonPropertyName("user_id")] + public string UserId { get; set; } = userId; + + [JsonPropertyName("reason")] + public string? Reason { get; set; } = reason; +} \ No newline at end of file diff --git a/LibMatrix/Responses/WhoAmIResponse.cs b/LibMatrix/Responses/WhoAmIResponse.cs new file mode 100644 index 0000000..db47152 --- /dev/null +++ b/LibMatrix/Responses/WhoAmIResponse.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; + +namespace LibMatrix.Responses; + +public class WhoAmIResponse { + [JsonPropertyName("user_id")] + public required string UserId { get; set; } + + [JsonPropertyName("device_id")] + public string? DeviceId { get; set; } + + [JsonPropertyName("is_guest")] + public bool? IsGuest { get; set; } +} \ No newline at end of file diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs index 2eb1dba..fd4db4d 100644 --- a/LibMatrix/RoomTypes/GenericRoom.cs +++ b/LibMatrix/RoomTypes/GenericRoom.cs @@ -1,6 +1,5 @@ using System.Collections.Frozen; using System.Net.Http.Json; -using System.Security.Cryptography; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; @@ -12,6 +11,7 @@ using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.Filters; using LibMatrix.Helpers; using LibMatrix.Homeservers; +using LibMatrix.Responses; namespace LibMatrix.RoomTypes; diff --git a/LibMatrix/RoomTypes/SpaceRoom.cs b/LibMatrix/RoomTypes/SpaceRoom.cs index 0c74be5..96abd77 100644 --- a/LibMatrix/RoomTypes/SpaceRoom.cs +++ b/LibMatrix/RoomTypes/SpaceRoom.cs @@ -1,5 +1,6 @@ using ArcaneLibs.Extensions; using LibMatrix.Homeservers; +using LibMatrix.Responses; namespace LibMatrix.RoomTypes; diff --git a/LibMatrix/UserIdAndReason.cs b/LibMatrix/UserIdAndReason.cs deleted file mode 100644 index 99c9eaf..0000000 --- a/LibMatrix/UserIdAndReason.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Text.Json.Serialization; - -namespace LibMatrix; - -internal class UserIdAndReason(string userId = null!, string reason = null!) { - [JsonPropertyName("user_id")] - public string UserId { get; set; } = userId; - - [JsonPropertyName("reason")] - public string? Reason { get; set; } = reason; -} \ No newline at end of file diff --git a/LibMatrix/WhoAmIResponse.cs b/LibMatrix/WhoAmIResponse.cs deleted file mode 100644 index 10fff35..0000000 --- a/LibMatrix/WhoAmIResponse.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Text.Json.Serialization; - -namespace LibMatrix; - -public class WhoAmIResponse { - [JsonPropertyName("user_id")] - public required string UserId { get; set; } - - [JsonPropertyName("device_id")] - public string? DeviceId { get; set; } - - [JsonPropertyName("is_guest")] - public bool? IsGuest { get; set; } -} \ No newline at end of file -- cgit 1.5.1