From cc61a7ae65d427e862e67ed92ec39f449cb23345 Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 23 Jan 2025 19:43:55 +0100 Subject: The rest of warning cleanup so far. --- LibMatrix/Extensions/CanonicalJsonSerializer.cs | 11 +++--- LibMatrix/Extensions/JsonElementExtensions.cs | 1 + LibMatrix/Extensions/MatrixHttpClient.Single.cs | 8 ++-- LibMatrix/Helpers/SyncHelper.cs | 17 +++------ LibMatrix/Helpers/SyncStateResolver.cs | 43 +++++++++++++--------- .../Homeservers/AuthenticatedHomeserverGeneric.cs | 18 ++++----- LibMatrix/Homeservers/RemoteHomeServer.cs | 20 ++++------ LibMatrix/LibMatrixException.cs | 3 ++ LibMatrix/MatrixException.cs | 5 ++- LibMatrix/Responses/CreateRoomRequest.cs | 15 ++++---- LibMatrix/RoomTypes/GenericRoom.cs | 13 ++++--- 11 files changed, 80 insertions(+), 74 deletions(-) (limited to 'LibMatrix') diff --git a/LibMatrix/Extensions/CanonicalJsonSerializer.cs b/LibMatrix/Extensions/CanonicalJsonSerializer.cs index c9d38cd..55a4b1a 100644 --- a/LibMatrix/Extensions/CanonicalJsonSerializer.cs +++ b/LibMatrix/Extensions/CanonicalJsonSerializer.cs @@ -8,7 +8,7 @@ namespace LibMatrix.Extensions; public static class CanonicalJsonSerializer { // TODO: Alphabetise dictionaries - private static JsonSerializerOptions _options => new() { + private static JsonSerializerOptions JsonOptions => new() { WriteIndented = false, Encoder = UnicodeJsonEncoder.Singleton, }; @@ -19,7 +19,7 @@ public static class CanonicalJsonSerializer { .ToFrozenSet(); private static JsonSerializerOptions MergeOptions(JsonSerializerOptions? inputOptions) { - var newOptions = _options; + var newOptions = JsonOptions; if (inputOptions == null) return newOptions; @@ -43,7 +43,7 @@ public static class CanonicalJsonSerializer { public static String Serialize(TValue value, JsonSerializerOptions? options = null) { var newOptions = MergeOptions(options); - return System.Text.Json.JsonSerializer.SerializeToNode(value, options) // We want to allow passing custom converters for eg. double/float -> string here... + return JsonSerializer.SerializeToNode(value, options) // We want to allow passing custom converters for eg. double/float -> string here... .SortProperties()! .CanonicalizeNumbers()! .ToJsonString(newOptions); @@ -53,13 +53,14 @@ public static class CanonicalJsonSerializer { } - public static String Serialize(object value, Type inputType, JsonSerializerOptions? options = null) => JsonSerializer.Serialize(value, inputType, _options); + public static String Serialize(object value, Type inputType, JsonSerializerOptions? options = null) => JsonSerializer.Serialize(value, inputType, JsonOptions); // public static String Serialize(TValue value, JsonTypeInfo jsonTypeInfo) => JsonSerializer.Serialize(value, jsonTypeInfo, _options); // public static String Serialize(Object value, JsonTypeInfo jsonTypeInfo) #endregion - private static partial class JsonExtensions { + // ReSharper disable once UnusedType.Local + private static class JsonExtensions { public static Action AlphabetizeProperties(Type type) { return typeInfo => { if (typeInfo.Kind != JsonTypeInfoKind.Object || !type.IsAssignableFrom(typeInfo.Type)) diff --git a/LibMatrix/Extensions/JsonElementExtensions.cs b/LibMatrix/Extensions/JsonElementExtensions.cs index c4ed743..dfec95b 100644 --- a/LibMatrix/Extensions/JsonElementExtensions.cs +++ b/LibMatrix/Extensions/JsonElementExtensions.cs @@ -126,6 +126,7 @@ public static class JsonElementExtensions { $"Encountered dictionary {field.Name} with key type {keyType.Name} and value type {valueType.Name}!"); return field.Value.EnumerateObject() + // TODO: use key.Value? .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) .Aggregate(false, (current, key) => current | key.FindExtraJsonPropertyFieldsByValueKind(containerType, valueType) diff --git a/LibMatrix/Extensions/MatrixHttpClient.Single.cs b/LibMatrix/Extensions/MatrixHttpClient.Single.cs index 895217d..56925fb 100644 --- a/LibMatrix/Extensions/MatrixHttpClient.Single.cs +++ b/LibMatrix/Extensions/MatrixHttpClient.Single.cs @@ -76,7 +76,7 @@ public class MatrixHttpClient { Console.WriteLine($"Sending {request.Method} {BaseAddress}{request.RequestUri} ({Util.BytesToString(request.GetContentLength())})"); if (request.RequestUri is null) throw new NullReferenceException("RequestUri is null"); - if (!request.RequestUri.IsAbsoluteUri) request.RequestUri = new Uri(BaseAddress, request.RequestUri); + if (!request.RequestUri.IsAbsoluteUri) request.RequestUri = new Uri(BaseAddress ?? throw new InvalidOperationException("Relative URI passed, but no BaseAddress is specified!"), request.RequestUri); foreach (var (key, value) in AdditionalQueryParameters) request.RequestUri = request.RequestUri.AddQuery(key, value); foreach (var (key, value) in DefaultRequestHeaders) { if (request.Headers.Contains(key)) continue; @@ -126,7 +126,7 @@ public class MatrixHttpClient { if (!content.StartsWith('{')) throw new InvalidDataException("Encountered invalid data:\n" + content); //we have a matrix error - MatrixException? ex = null; + MatrixException? ex; try { ex = JsonSerializer.Deserialize(content); } @@ -140,7 +140,7 @@ public class MatrixHttpClient { Debug.Assert(ex != null, nameof(ex) + " != null"); ex.RawContent = content; // Console.WriteLine($"Failed to send request: {ex}"); - if (ex?.RetryAfterMs is null) throw ex!; + if (ex.RetryAfterMs is null) throw ex!; //we have a ratelimit error await Task.Delay(ex.RetryAfterMs.Value, cancellationToken); request.ResetSendStatus(); @@ -179,7 +179,7 @@ public class MatrixHttpClient { } // GetStreamAsync - public new async Task GetStreamAsync(string requestUri, CancellationToken cancellationToken = default) { + public async Task GetStreamAsync(string requestUri, CancellationToken cancellationToken = default) { var request = new HttpRequestMessage(HttpMethod.Get, requestUri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await SendAsync(request, cancellationToken); diff --git a/LibMatrix/Helpers/SyncHelper.cs b/LibMatrix/Helpers/SyncHelper.cs index aed56a7..05bfb47 100644 --- a/LibMatrix/Helpers/SyncHelper.cs +++ b/LibMatrix/Helpers/SyncHelper.cs @@ -1,12 +1,10 @@ using System.Diagnostics; -using System.Net.Http.Json; using System.Text.Json; using ArcaneLibs.Collections; using ArcaneLibs.Extensions; using LibMatrix.Filters; using LibMatrix.Homeservers; using LibMatrix.Responses; -using LibMatrix.Utilities; using Microsoft.Extensions.Logging; namespace LibMatrix.Helpers; @@ -14,8 +12,8 @@ namespace LibMatrix.Helpers; public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logger = null) { private SyncFilter? _filter; private string? _namedFilterName; - private bool _filterIsDirty = false; - private string? _filterId = null; + private bool _filterIsDirty; + private string? _filterId; public string? Since { get; set; } public int Timeout { get; set; } = 30000; @@ -55,7 +53,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg public TimeSpan MinimumDelay { get; set; } = new(0); - private async Task updateFilterAsync() { + private async Task UpdateFilterAsync() { if (!string.IsNullOrWhiteSpace(NamedFilterName)) { _filterId = await homeserver.NamedCaches.FilterCache.GetOrSetValueAsync(NamedFilterName); if (_filterId is null) @@ -79,7 +77,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg } var sw = Stopwatch.StartNew(); - if (_filterIsDirty) await updateFilterAsync(); + if (_filterIsDirty) await UpdateFilterAsync(); var url = $"/_matrix/client/v3/sync?timeout={Timeout}&set_presence={SetPresence}&full_state={(FullState ? "true" : "false")}"; if (!string.IsNullOrWhiteSpace(Since)) url += $"&since={Since}"; @@ -189,7 +187,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg if (syncResponse.Rooms is { Join.Count: > 0 }) foreach (var updatedRoom in syncResponse.Rooms.Join) { if (updatedRoom.Value.Timeline is null) continue; - foreach (var stateEventResponse in updatedRoom.Value.Timeline.Events) { + foreach (var stateEventResponse in updatedRoom.Value.Timeline.Events ?? []) { stateEventResponse.RoomId = updatedRoom.Key; var tasks = TimelineEventHandlers.Select(x => x(stateEventResponse)).ToList(); await Task.WhenAll(tasks); @@ -216,9 +214,4 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg /// Event fired when an account data event is received /// public List> AccountDataReceivedHandlers { get; } = new(); - - private void Log(string message) { - if (logger is null) Console.WriteLine(message); - else logger.LogInformation(message); - } } \ No newline at end of file diff --git a/LibMatrix/Helpers/SyncStateResolver.cs b/LibMatrix/Helpers/SyncStateResolver.cs index 72d600d..4633f06 100644 --- a/LibMatrix/Helpers/SyncStateResolver.cs +++ b/LibMatrix/Helpers/SyncStateResolver.cs @@ -27,14 +27,13 @@ public class SyncStateResolver(AuthenticatedHomeserverGeneric homeserver, ILogge // run sync var sync = await _syncHelper.SyncAsync(cancellationToken); if (sync is null) return await ContinueAsync(cancellationToken); - if (MergedState is null) MergedState = sync; - else MergedState = MergeSyncs(MergedState, sync); + MergedState = MergedState is null ? sync : MergeSyncs(MergedState, sync); Since = sync.NextBatch; return (sync, MergedState); } private SyncResponse MergeSyncs(SyncResponse oldState, SyncResponse newState) { - oldState.NextBatch = newState.NextBatch ?? oldState.NextBatch; + oldState.NextBatch = newState.NextBatch; oldState.AccountData ??= new EventList(); oldState.AccountData.Events ??= new List(); @@ -42,8 +41,11 @@ public class SyncStateResolver(AuthenticatedHomeserverGeneric homeserver, ILogge oldState.AccountData.Events.MergeStateEventLists(newState.AccountData?.Events ?? new List()); oldState.Presence ??= new SyncResponse.PresenceDataStructure(); - if (newState.Presence?.Events is not null) - oldState.Presence.Events.MergeStateEventLists(newState.Presence?.Events ?? new List()); + if (newState.Presence?.Events is { Count: > 0 }) + if (oldState.Presence.Events is { Count: > 0 }) + oldState.Presence.Events.MergeStateEventLists(newState.Presence.Events); + else + oldState.Presence.Events = newState.Presence?.Events; oldState.DeviceOneTimeKeysCount ??= new Dictionary(); if (newState.DeviceOneTimeKeysCount is not null) @@ -60,12 +62,17 @@ public class SyncStateResolver(AuthenticatedHomeserverGeneric homeserver, ILogge oldState.ToDevice.Events.MergeStateEventLists(newState.ToDevice?.Events ?? new List()); oldState.DeviceLists ??= new SyncResponse.DeviceListsDataStructure(); - if (newState.DeviceLists?.Changed is not null) - foreach (var s in oldState.DeviceLists.Changed!) + if (newState.DeviceLists?.Changed is not null) { + oldState.DeviceLists.Changed ??= new List(); + foreach (var s in newState.DeviceLists.Changed) oldState.DeviceLists.Changed.Add(s); - if (newState.DeviceLists?.Left is not null) - foreach (var s in oldState.DeviceLists.Left!) + } + + if (newState.DeviceLists?.Left is not null) { + oldState.DeviceLists.Left ??= new List(); + foreach (var s in newState.DeviceLists.Left) oldState.DeviceLists.Left.Add(s); + } return oldState; } @@ -75,18 +82,18 @@ public class SyncStateResolver(AuthenticatedHomeserverGeneric homeserver, ILogge private SyncResponse.RoomsDataStructure MergeRoomsDataStructure(SyncResponse.RoomsDataStructure oldState, SyncResponse.RoomsDataStructure newState) { oldState.Join ??= new Dictionary(); foreach (var (key, value) in newState.Join ?? new Dictionary()) - if (!oldState.Join.ContainsKey(key)) oldState.Join[key] = value; - else oldState.Join[key] = MergeJoinedRoomDataStructure(oldState.Join[key], value); + if (!oldState.Join.TryAdd(key, value)) + oldState.Join[key] = MergeJoinedRoomDataStructure(oldState.Join[key], value); oldState.Invite ??= new Dictionary(); foreach (var (key, value) in newState.Invite ?? new Dictionary()) - if (!oldState.Invite.ContainsKey(key)) oldState.Invite[key] = value; - else oldState.Invite[key] = MergeInvitedRoomDataStructure(oldState.Invite[key], value); + if (!oldState.Invite.TryAdd(key, value)) + oldState.Invite[key] = MergeInvitedRoomDataStructure(oldState.Invite[key], value); oldState.Leave ??= new Dictionary(); foreach (var (key, value) in newState.Leave ?? new Dictionary()) { - if (!oldState.Leave.ContainsKey(key)) oldState.Leave[key] = value; - else oldState.Leave[key] = MergeLeftRoomDataStructure(oldState.Leave[key], value); + if (!oldState.Leave.TryAdd(key, value)) + oldState.Leave[key] = MergeLeftRoomDataStructure(oldState.Leave[key], value); if (oldState.Invite.ContainsKey(key)) oldState.Invite.Remove(key); if (oldState.Join.ContainsKey(key)) oldState.Join.Remove(key); } @@ -157,9 +164,9 @@ public class SyncStateResolver(AuthenticatedHomeserverGeneric homeserver, ILogge oldData.UnreadNotifications.NotificationCount = newData.UnreadNotifications?.NotificationCount ?? oldData.UnreadNotifications.NotificationCount; oldData.Summary ??= new SyncResponse.RoomsDataStructure.JoinedRoomDataStructure.SummaryDataStructure { - Heroes = newData.Summary?.Heroes ?? oldData.Summary.Heroes, - JoinedMemberCount = newData.Summary?.JoinedMemberCount ?? oldData.Summary.JoinedMemberCount, - InvitedMemberCount = newData.Summary?.InvitedMemberCount ?? oldData.Summary.InvitedMemberCount + Heroes = newData.Summary?.Heroes ?? oldData.Summary?.Heroes, + JoinedMemberCount = newData.Summary?.JoinedMemberCount ?? oldData.Summary?.JoinedMemberCount, + InvitedMemberCount = newData.Summary?.InvitedMemberCount ?? oldData.Summary?.InvitedMemberCount }; oldData.Summary.Heroes = newData.Summary?.Heroes ?? oldData.Summary.Heroes; oldData.Summary.JoinedMemberCount = newData.Summary?.JoinedMemberCount ?? oldData.Summary.JoinedMemberCount; diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs index 40d7fb4..f47ab64 100644 --- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs +++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs @@ -375,11 +375,11 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { /// All account data. /// public async Task EnumerateAccountData() { - var syncHelper = new SyncHelper(this); - syncHelper.FilterId = await NamedCaches.FilterCache.GetOrSetValueAsync(CommonSyncFilters.GetAccountData); + var syncHelper = new SyncHelper(this) { + FilterId = await NamedCaches.FilterCache.GetOrSetValueAsync(CommonSyncFilters.GetAccountData) + }; var resp = await syncHelper.SyncAsync(); - if (resp is null) throw new Exception("Sync failed"); - return resp.AccountData; + return resp?.AccountData ?? throw new Exception("Sync failed"); } private Dictionary? _namedFilterCache; @@ -431,7 +431,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { //fallback to legacy media try { - var uri = $"/_matrix/media/v1/download/{serverName}/{mediaId}"; + var uri = $"/_matrix/media/v3/download/{serverName}/{mediaId}"; if (!string.IsNullOrWhiteSpace(filename)) uri += $"/{HttpUtility.UrlEncode(filename)}"; if (timeout is not null) uri += $"?timeout_ms={timeout}"; var res = await ClientHttpClient.GetAsync(uri); @@ -455,7 +455,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { uri = uri.AddQuery("width", width.ToString()); uri = uri.AddQuery("height", height.ToString()); if (!string.IsNullOrWhiteSpace(method)) uri = uri.AddQuery("method", method); - if (timeout is not null) uri = uri.AddQuery("timeout_ms", timeout.ToString()); + if (timeout is not null) uri = uri.AddQuery("timeout_ms", timeout.ToString()!); var res = await ClientHttpClient.GetAsync(uri.ToString()); return await res.Content.ReadAsStreamAsync(); @@ -466,11 +466,11 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { //fallback to legacy media try { - var uri = new Uri($"/_matrix/media/v1/thumbnail/{serverName}/{mediaId}"); + var uri = new Uri($"/_matrix/media/v3/thumbnail/{serverName}/{mediaId}"); uri = uri.AddQuery("width", width.ToString()); uri = uri.AddQuery("height", height.ToString()); if (!string.IsNullOrWhiteSpace(method)) uri = uri.AddQuery("method", method); - if (timeout is not null) uri = uri.AddQuery("timeout_ms", timeout.ToString()); + if (timeout is not null) uri = uri.AddQuery("timeout_ms", timeout.ToString()!); var res = await ClientHttpClient.GetAsync(uri.ToString()); return await res.Content.ReadAsStreamAsync(); @@ -497,7 +497,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { //fallback to legacy media try { - var res = await ClientHttpClient.GetAsync($"/_matrix/media/v1/preview_url?url={HttpUtility.UrlEncode(url)}"); + var res = await ClientHttpClient.GetAsync($"/_matrix/media/v3/preview_url?url={HttpUtility.UrlEncode(url)}"); return await res.Content.ReadFromJsonAsync>(); } catch (MatrixException e) { diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs index ee70dc3..7995f03 100644 --- a/LibMatrix/Homeservers/RemoteHomeServer.cs +++ b/LibMatrix/Homeservers/RemoteHomeServer.cs @@ -49,7 +49,7 @@ public class RemoteHomeserver { var resp = await ClientHttpClient.GetAsync($"/_matrix/client/v3/profile/{HttpUtility.UrlEncode(mxid)}"); var data = await resp.Content.ReadFromJsonAsync(); if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data); - _profileCache[mxid] = data; + _profileCache[mxid] = data ?? throw new InvalidOperationException($"Could not get profile for {mxid}"); return data; } @@ -58,7 +58,7 @@ public class RemoteHomeserver { var resp = await ClientHttpClient.GetAsync($"/_matrix/client/versions"); var data = await resp.Content.ReadFromJsonAsync(); if (!resp.IsSuccessStatusCode) Console.WriteLine("ClientVersions: " + data); - return data; + return data ?? throw new InvalidOperationException("ClientVersionsResponse is null"); } public async Task ResolveRoomAliasAsync(string alias) { @@ -66,7 +66,7 @@ public class RemoteHomeserver { var data = await resp.Content.ReadFromJsonAsync(); //var text = await resp.Content.ReadAsStringAsync(); if (!resp.IsSuccessStatusCode) Console.WriteLine("ResolveAlias: " + data.ToJson()); - return data; + return data ?? throw new InvalidOperationException($"Could not resolve alias {alias}"); } #region Authentication @@ -78,12 +78,11 @@ public class RemoteHomeserver { type = "m.id.user", user = username }, - password = password, + password, initial_device_display_name = deviceName }); var data = await resp.Content.ReadFromJsonAsync(); - if (!resp.IsSuccessStatusCode) Console.WriteLine("Login: " + data.ToJson()); - return data; + return data ?? throw new InvalidOperationException("LoginResponse is null"); } public async Task RegisterAsync(string username, string password, string? deviceName = null) { @@ -99,18 +98,13 @@ public class RemoteHomeserver { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); var data = await resp.Content.ReadFromJsonAsync(); - if (!resp.IsSuccessStatusCode) Console.WriteLine("Register: " + data.ToJson()); - return data; + return data ?? throw new InvalidOperationException("LoginResponse is null"); } #endregion [Obsolete("This call uses the deprecated unauthenticated media endpoints, please switch to the relevant AuthenticatedHomeserver methods instead.", true)] - public string? ResolveMediaUri(string? mxcUri) { - if (mxcUri is null) return null; - if (mxcUri.StartsWith("https://")) return mxcUri; - return $"{ClientHttpClient.BaseAddress}/_matrix/media/v3/download/{mxcUri.Replace("mxc://", "")}".Replace("//_matrix", "/_matrix"); - } + public virtual string? ResolveMediaUri(string? mxcUri) => null; public UserInteractiveAuthClient Auth; } diff --git a/LibMatrix/LibMatrixException.cs b/LibMatrix/LibMatrixException.cs index 5854826..27cfc2a 100644 --- a/LibMatrix/LibMatrixException.cs +++ b/LibMatrix/LibMatrixException.cs @@ -1,5 +1,7 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using ArcaneLibs.Extensions; +// ReSharper disable MemberCanBePrivate.Global namespace LibMatrix; @@ -20,6 +22,7 @@ public class LibMatrixException : Exception { _ => $"Unknown error: {GetAsObject().ToJson(ignoreNull: true)}" }}\nError: {Error}"; + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Follows spec naming")] public static class ErrorCodes { public const string M_NOT_FOUND = "M_NOT_FOUND"; public const string M_UNSUPPORTED = "M_UNSUPPORTED"; diff --git a/LibMatrix/MatrixException.cs b/LibMatrix/MatrixException.cs index eb207da..3a79af8 100644 --- a/LibMatrix/MatrixException.cs +++ b/LibMatrix/MatrixException.cs @@ -1,5 +1,7 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; using ArcaneLibs.Extensions; +// ReSharper disable MemberCanBePrivate.Global namespace LibMatrix; @@ -17,7 +19,7 @@ public class MatrixException : Exception { [JsonPropertyName("retry_after_ms")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public int? RetryAfterMs { get; set; } - + public string RawContent { get; set; } public object GetAsObject() => new { errcode = ErrorCode, error = Error, soft_logout = SoftLogout, retry_after_ms = RetryAfterMs }; @@ -62,6 +64,7 @@ public class MatrixException : Exception { _ => $"Unknown error: {new { ErrorCode, Error, SoftLogout, RetryAfterMs }.ToJson(ignoreNull: true)}" }}"; + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Follows spec naming")] public static class ErrorCodes { public const string M_FORBIDDEN = "M_FORBIDDEN"; public const string M_UNKNOWN_TOKEN = "M_UNKNOWN_TOKEN"; diff --git a/LibMatrix/Responses/CreateRoomRequest.cs b/LibMatrix/Responses/CreateRoomRequest.cs index 38bc970..741bea1 100644 --- a/LibMatrix/Responses/CreateRoomRequest.cs +++ b/LibMatrix/Responses/CreateRoomRequest.cs @@ -36,10 +36,11 @@ public class CreateRoomRequest { /// One of: ["public", "private"] /// [JsonPropertyName("visibility")] + // ReSharper disable once UnusedAutoPropertyAccessor.Global public string? Visibility { get; set; } [JsonPropertyName("power_level_content_override")] - public RoomPowerLevelEventContent? PowerLevelContentOverride { get; set; } = null!; + public RoomPowerLevelEventContent? PowerLevelContentOverride { get; set; } [JsonPropertyName("creation_content")] public JsonObject CreationContent { get; set; } = new(); @@ -51,11 +52,11 @@ public class CreateRoomRequest { /// For use only when you can't use the CreationContent property /// - public StateEvent this[string eventType, string eventKey = ""] { + public StateEvent? this[string eventType, string eventKey = ""] { get { - var stateEvent = InitialState.FirstOrDefault(x => x.Type == eventType && x.StateKey == eventKey); + var stateEvent = InitialState?.FirstOrDefault(x => x.Type == eventType && x.StateKey == eventKey); if (stateEvent == null) - InitialState.Add(stateEvent = new StateEvent { + InitialState?.Add(stateEvent = new StateEvent { Type = eventType, StateKey = eventKey, TypedContent = (EventContent)Activator.CreateInstance( @@ -78,7 +79,7 @@ public class CreateRoomRequest { public Dictionary Validate() { Dictionary errors = new(); - if (!Regex.IsMatch(RoomAliasName, @"[a-zA-Z0-9_\-]+$")) + if (!string.IsNullOrWhiteSpace(RoomAliasName) && !Regex.IsMatch(RoomAliasName, @"[a-zA-Z0-9_\-]+$")) errors.Add("room_alias_name", "Room alias name must only contain letters, numbers, underscores, and hyphens."); @@ -98,7 +99,7 @@ public class CreateRoomRequest { Invite = 25, StateDefault = 10, Redact = 50, - NotificationsPl = new RoomPowerLevelEventContent.NotificationsPL { + NotificationsPl = new RoomPowerLevelEventContent.NotificationsPowerLevels { Room = 10 }, Events = new Dictionary { @@ -138,7 +139,7 @@ public class CreateRoomRequest { Invite = 25, StateDefault = 10, Redact = 50, - NotificationsPl = new RoomPowerLevelEventContent.NotificationsPL { + NotificationsPl = new RoomPowerLevelEventContent.NotificationsPowerLevels { Room = 10 }, Events = new Dictionary { diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs index b8e68f8..14276d7 100644 --- a/LibMatrix/RoomTypes/GenericRoom.cs +++ b/LibMatrix/RoomTypes/GenericRoom.cs @@ -135,7 +135,7 @@ public class GenericRoom { return await GetStateEventAsync(type, stateKey); } catch (MatrixException e) { - if (e.ErrorCode == "M_NOT_FOUND") return default; + if (e.ErrorCode == "M_NOT_FOUND") return null; throw; } } @@ -237,10 +237,11 @@ public class GenericRoom { var result = await JsonSerializer.DeserializeAsync(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() { TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default }); + if (result is null) throw new Exception("Failed to deserialise members response"); // if (sw.ElapsedMilliseconds > 100) // Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}"); // else sw.Restart(); - foreach (var resp in result.Chunk) { + foreach (var resp in result.Chunk ?? []) { if (resp?.Type != "m.room.member") continue; if (joinedOnly && resp.RawContent?["membership"]?.GetValue() != "join") continue; yield return resp; @@ -261,11 +262,12 @@ public class GenericRoom { var result = await JsonSerializer.DeserializeAsync(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() { TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default }); + if (result is null) throw new Exception("Failed to deserialise members response"); // if (sw.ElapsedMilliseconds > 100) // Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}"); // else sw.Restart(); var members = new List(); - foreach (var resp in result.Chunk) { + foreach (var resp in result.Chunk ?? []) { if (resp?.Type != "m.room.member") continue; if (joinedOnly && resp.RawContent?["membership"]?.GetValue() != "join") continue; members.Add(resp); @@ -428,7 +430,7 @@ public class GenericRoom { return await res.Content.ReadFromJsonAsync(); } - + public async Task GetRoomAccountDataOrNullAsync(string key) { try { return await GetRoomAccountDataAsync(key); @@ -456,7 +458,8 @@ public class GenericRoom { while (true) { try { return (await (await Homeserver.ClientHttpClient.PutAsJsonAsync(url, data)).Content.ReadFromJsonAsync())!; - } catch (MatrixException e) { + } + catch (MatrixException e) { if (e is { ErrorCode: MatrixException.ErrorCodes.M_FORBIDDEN }) throw; throw; } -- cgit 1.5.1