about summary refs log tree commit diff
path: root/MatrixRoomUtils.Core
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixRoomUtils.Core')
-rw-r--r--MatrixRoomUtils.Core/Extensions/ClassCollector.cs10
-rw-r--r--MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs28
-rw-r--r--MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs154
-rw-r--r--MatrixRoomUtils.Core/Filters/SyncFilter.cs68
-rw-r--r--MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs2
-rw-r--r--MatrixRoomUtils.Core/Responses/StateEventResponse.cs20
-rw-r--r--MatrixRoomUtils.Core/StateEvent.cs23
-rw-r--r--MatrixRoomUtils.Core/StateEventStruct.cs12
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs16
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs18
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs14
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs (renamed from MatrixRoomUtils.Core/StateEventTypes/Spec/PowerLevelEventData.cs)16
12 files changed, 257 insertions, 124 deletions
diff --git a/MatrixRoomUtils.Core/Extensions/ClassCollector.cs b/MatrixRoomUtils.Core/Extensions/ClassCollector.cs

index 9d3d3c0..d4ba838 100644 --- a/MatrixRoomUtils.Core/Extensions/ClassCollector.cs +++ b/MatrixRoomUtils.Core/Extensions/ClassCollector.cs
@@ -19,12 +19,4 @@ public class ClassCollector<T> where T : class { public List<Type> ResolveFromAssembly(Assembly assembly) => assembly.GetTypes() .Where(x => x is { IsClass: true, IsAbstract: false } && x.GetInterfaces().Contains(typeof(T))).ToList(); - // { - // List<Type> ret = new(); - // foreach (var x in assembly.GetTypes().Where(x => x is { IsClass: true, IsAbstract: false } && x.GetInterfaces().Contains(typeof(T))).ToList()) { - // // Console.WriteLine($"[!!] Found class {x.FullName}"); - // ret.Add(x); - // } - // return ret; - // } -} \ No newline at end of file +} diff --git a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
index 695e8e3..9ac9c6b 100644 --- a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs +++ b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
@@ -19,40 +19,42 @@ public static class HttpClientExtensions { } public class MatrixHttpClient : HttpClient { - public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { - Console.WriteLine($"Sending request to {request.RequestUri}"); - try - { - HttpRequestOptionsKey<bool> WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingResponse"); + public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) { + Console.WriteLine($"Sending request to {request.RequestUri}"); + try { + HttpRequestOptionsKey<bool> WebAssemblyEnableStreamingResponseKey = + new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingResponse"); request.Options.Set(WebAssemblyEnableStreamingResponseKey, true); - // var asm = Assembly.Load("Microsoft.AspNetCore.Components.WebAssembly"); - // var browserHttpHandlerType = asm.GetType("Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions", true); - // var browserHttpHandlerMethod = browserHttpHandlerType.GetMethod("SetBrowserResponseStreamingEnabled", BindingFlags.Public | BindingFlags.Static); - // browserHttpHandlerMethod?.Invoke(null, new object[] {request, true}); } - catch (Exception e) - { + catch (Exception e) { Console.WriteLine("Failed to set browser response streaming:"); Console.WriteLine(e); } + var a = await base.SendAsync(request, cancellationToken); if (!a.IsSuccessStatusCode) { var content = await a.Content.ReadAsStringAsync(cancellationToken); if (content.StartsWith('{')) { var ex = JsonSerializer.Deserialize<MatrixException>(content); ex.RawContent = content; - Console.WriteLine($"Failed to send request: {ex}"); + Console.WriteLine($"Failed to send request: {ex}"); if (ex?.RetryAfterMs is not null) { await Task.Delay(ex.RetryAfterMs.Value, cancellationToken); - typeof(HttpRequestMessage).GetField("_sendStatus", BindingFlags.NonPublic | BindingFlags.Instance)?.SetValue(request, 0); + typeof(HttpRequestMessage).GetField("_sendStatus", BindingFlags.NonPublic | BindingFlags.Instance) + ?.SetValue(request, 0); return await SendAsync(request, cancellationToken); } + throw ex!; } + throw new InvalidDataException("Encountered invalid data:\n" + content); } + return a; } + // GetFromJsonAsync public async Task<T> GetFromJsonAsync<T>(string requestUri, CancellationToken cancellationToken = default) { var request = new HttpRequestMessage(HttpMethod.Get, requestUri); diff --git a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
index 36da644..7701c9e 100644 --- a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs +++ b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
@@ -3,37 +3,149 @@ using System.Reflection; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; +using MatrixRoomUtils.Core.Responses; namespace MatrixRoomUtils.Core.Extensions; public static class JsonElementExtensions { - public static bool FindExtraJsonElementFields([DisallowNull] this JsonElement? res, Type t) { - var props = t.GetProperties(); - var unknownPropertyFound = false; - foreach (var field in res.Value.EnumerateObject()) { - if (props.Any(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name == field.Name)) continue; - Console.WriteLine($"[!!] Unknown property {field.Name} in {t.Name}!"); + public static bool FindExtraJsonElementFields(this JsonElement obj, Type objectType, string objectPropertyName) { + if (objectPropertyName == "content" && objectType == typeof(JsonObject)) + objectType = typeof(StateEventResponse); + // if (t == typeof(JsonNode)) + // return false; + + Console.WriteLine($"{objectType.Name} {objectPropertyName}"); + bool unknownPropertyFound = false; + var mappedPropsDict = objectType.GetProperties() + .Where(x => x.GetCustomAttribute<JsonPropertyNameAttribute>() is not null) + .ToDictionary(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()!.Name, x => x); + objectType.GetProperties().Where(x => !mappedPropsDict.ContainsKey(x.Name)) + .ToList().ForEach(x => mappedPropsDict.TryAdd(x.Name, x)); + + foreach (var field in obj.EnumerateObject()) { + if (mappedPropsDict.TryGetValue(field.Name, out var mappedProperty)) { + //dictionary + if (mappedProperty.PropertyType.IsGenericType && + mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { + unknownPropertyFound |= _checkDictionary(field, objectType, mappedProperty.PropertyType); + continue; + } + + if (mappedProperty.PropertyType.IsGenericType && + mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) { + unknownPropertyFound |= _checkList(field, objectType, mappedProperty.PropertyType); + continue; + } + + if (field.Name == "content" && (objectType == typeof(StateEventResponse) || objectType == typeof(StateEvent))) { + unknownPropertyFound |= field.FindExtraJsonPropertyFieldsByValueKind( + StateEvent.GetStateEventType(obj.GetProperty("type").GetString()), + mappedProperty.PropertyType); + continue; + } + + unknownPropertyFound |= + field.FindExtraJsonPropertyFieldsByValueKind(objectType, mappedProperty.PropertyType); + continue; + } + + Console.WriteLine($"[!!] Unknown property {field.Name} in {objectType.Name}!"); unknownPropertyFound = true; } - if (unknownPropertyFound) Console.WriteLine(res.Value.ToJson()); - return unknownPropertyFound; } - public static bool FindExtraJsonObjectFields([DisallowNull] this JsonObject? res, Type t) { - var props = t.GetProperties(); - var unknownPropertyFound = false; - foreach (var field in res) { - if (props.Any(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name == field.Key)) continue; - Console.WriteLine($"[!!] Unknown property {field.Key} in {t.Name}!"); - unknownPropertyFound = true; - // foreach (var propertyInfo in props) { - // Console.WriteLine($"[!!] Known property {propertyInfo.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name} in {t.Name}!"); - // } + + private static bool FindExtraJsonPropertyFieldsByValueKind(this JsonProperty field, Type containerType, + Type propertyType) { + if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { + propertyType = propertyType.GetGenericArguments()[0]; } - if (unknownPropertyFound) Console.WriteLine(res.ToJson()); + bool switchResult = false; + switch (field.Value.ValueKind) { + case JsonValueKind.Array: + switchResult = field.Value.EnumerateArray().Aggregate(switchResult, + (current, element) => current | element.FindExtraJsonElementFields(propertyType, field.Name)); + break; + case JsonValueKind.Object: + switchResult |= field.Value.FindExtraJsonElementFields(propertyType, field.Name); + break; + case JsonValueKind.True: + case JsonValueKind.False: + return _checkBool(field, containerType, propertyType); + case JsonValueKind.String: + return _checkString(field, containerType, propertyType); + case JsonValueKind.Number: + return _checkNumber(field, containerType, propertyType); + case JsonValueKind.Undefined: + case JsonValueKind.Null: + break; + default: + throw new ArgumentOutOfRangeException(); + } - return unknownPropertyFound; + return switchResult; + } + + private static bool _checkBool(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(bool)) return true; + Console.WriteLine( + $"[!!] Encountered bool for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkString(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(string)) return true; + // ReSharper disable once BuiltInTypeReferenceStyle + if (propertyType == typeof(String)) return true; + Console.WriteLine( + $"[!!] Encountered string for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkNumber(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(int) || + propertyType == typeof(double) || + propertyType == typeof(float) || + propertyType == typeof(decimal) || + propertyType == typeof(long) || + propertyType == typeof(short) || + propertyType == typeof(uint) || + propertyType == typeof(ulong) || + propertyType == typeof(ushort) || + propertyType == typeof(byte) || + propertyType == typeof(sbyte)) + return true; + Console.WriteLine( + $"[!!] Encountered number for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkDictionary(this JsonProperty field, Type containerType, Type propertyType) { + var keyType = propertyType.GetGenericArguments()[0]; + var valueType = propertyType.GetGenericArguments()[1]; + valueType = Nullable.GetUnderlyingType(valueType) ?? valueType; + Console.WriteLine( + $"Encountered dictionary {field.Name} with key type {keyType.Name} and value type {valueType.Name}!"); + + return field.Value.EnumerateObject() + .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) + .Aggregate(false, (current, key) => + current | key.FindExtraJsonPropertyFieldsByValueKind(containerType, valueType) + ); + } + + private static bool _checkList(this JsonProperty field, Type containerType, Type propertyType) { + var valueType = propertyType.GetGenericArguments()[0]; + valueType = Nullable.GetUnderlyingType(valueType) ?? valueType; + Console.WriteLine( + $"Encountered list {field.Name} with value type {valueType.Name}!"); + + return field.Value.EnumerateArray() + .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) + .Aggregate(false, (current, key) => + current | key.FindExtraJsonElementFields(valueType, field.Name) + ); } -} \ No newline at end of file +} diff --git a/MatrixRoomUtils.Core/Filters/SyncFilter.cs b/MatrixRoomUtils.Core/Filters/SyncFilter.cs
index 7957898..bc81101 100644 --- a/MatrixRoomUtils.Core/Filters/SyncFilter.cs +++ b/MatrixRoomUtils.Core/Filters/SyncFilter.cs
@@ -4,47 +4,50 @@ namespace MatrixRoomUtils.Core.Filters; public class SyncFilter { [JsonPropertyName("account_data")] - public AccountDataFilter? AccountData { get; set; } + public EventFilter? AccountData { get; set; } [JsonPropertyName("presence")] - public PresenceFilter? Presence { get; set; } + public EventFilter? Presence { get; set; } [JsonPropertyName("room")] public RoomFilter? Room { get; set; } -} -public class PresenceFilter { - [JsonPropertyName("not_types")] - public List<string>? NotTypes { get; set; } -} + public class RoomFilter { + [JsonPropertyName("account_data")] + public StateFilter? AccountData { get; set; } -public class RoomFilter { - [JsonPropertyName("account_data")] - public AccountDataFilter? AccountData { get; set; } + [JsonPropertyName("ephemeral")] + public StateFilter? Ephemeral { get; set; } - [JsonPropertyName("ephemeral")] - public EphemeralFilter? Ephemeral { get; set; } + [JsonPropertyName("state")] + public StateFilter? State { get; set; } - public class EphemeralFilter { - [JsonPropertyName("not_types")] - public List<string>? NotTypes { get; set; } - } + [JsonPropertyName("timeline")] + public StateFilter? Timeline { get; set; } - [JsonPropertyName("state")] - public StateFilter? State { get; set; } - public class StateFilter { - [JsonPropertyName("lazy_load_members")] - public bool? LazyLoadMembers { get; set; } + public class StateFilter : EventFilter { + [JsonPropertyName("contains_url")] + public bool? ContainsUrl { get; set; } - [JsonPropertyName("types")] - public List<string>? Types { get; set; } - } + [JsonPropertyName("include_redundant_members")] + public bool? IncludeRedundantMembers { get; set; } + + [JsonPropertyName("lazy_load_members")] + public bool? LazyLoadMembers { get; set; } + + [JsonPropertyName("rooms")] + public List<string>? Rooms { get; set; } + + [JsonPropertyName("not_rooms")] + public List<string>? NotRooms { get; set; } - [JsonPropertyName("timeline")] - public TimelineFilter? Timeline { get; set; } + [JsonPropertyName("unread_thread_notifications")] + public bool? UnreadThreadNotifications { get; set; } + } + } - public class TimelineFilter { + public class EventFilter { [JsonPropertyName("limit")] public int? Limit { get; set; } @@ -53,10 +56,11 @@ public class RoomFilter { [JsonPropertyName("not_types")] public List<string>? NotTypes { get; set; } + + [JsonPropertyName("senders")] + public List<string>? Senders { get; set; } + + [JsonPropertyName("not_senders")] + public List<string>? NotSenders { get; set; } } } - -public class AccountDataFilter { - [JsonPropertyName("not_types")] - public List<string>? NotTypes { get; set; } -} \ No newline at end of file diff --git a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
index be78a97..540a323 100644 --- a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs +++ b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
@@ -31,7 +31,7 @@ public class CreateRoomRequest { public string Visibility { get; set; } = null!; [JsonPropertyName("power_level_content_override")] - public PowerLevelEventData PowerLevelContentOverride { get; set; } = null!; + public RoomPowerLevelEventData PowerLevelContentOverride { get; set; } = null!; [JsonPropertyName("creation_content")] public JsonObject CreationContent { get; set; } = new(); diff --git a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
index 422a557..a7f9187 100644 --- a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs +++ b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
@@ -1,3 +1,4 @@ +using System.Text.Json.Nodes; using System.Text.Json.Serialization; using MatrixRoomUtils.Core.Interfaces; @@ -25,20 +26,23 @@ public class StateEventResponse : StateEvent { [JsonPropertyName("replaces_state")] public string ReplacesState { get; set; } - [JsonPropertyName("prev_content")] - public dynamic PrevContent { get; set; } - public class UnsignedData { [JsonPropertyName("age")] public ulong? Age { get; set; } - [JsonPropertyName("prev_content")] - public dynamic? PrevContent { get; set; } - [JsonPropertyName("redacted_because")] - public dynamic? RedactedBecause { get; set; } + public object? RedactedBecause { get; set; } [JsonPropertyName("transaction_id")] public string? TransactionId { get; set; } + + [JsonPropertyName("replaces_state")] + public string? ReplacesState { get; set; } + + [JsonPropertyName("prev_sender")] + public string? PrevSender { get; set; } + + [JsonPropertyName("prev_content")] + public JsonObject? PrevContent { get; set; } } -} \ No newline at end of file +} diff --git a/MatrixRoomUtils.Core/StateEvent.cs b/MatrixRoomUtils.Core/StateEvent.cs
index 1c0a1cf..785c637 100644 --- a/MatrixRoomUtils.Core/StateEvent.cs +++ b/MatrixRoomUtils.Core/StateEvent.cs
@@ -14,6 +14,17 @@ public class StateEvent { public static List<Type> KnownStateEventTypes = new ClassCollector<IStateEventType>().ResolveFromAllAccessibleAssemblies(); + public static Type GetStateEventType(string type) { + if (type == "m.receipt") { + return typeof(Dictionary<string, JsonObject>); + } + + var eventType = KnownStateEventTypes.FirstOrDefault(x => + x.GetCustomAttributes<MatrixEventAttribute>()?.Any(y => y.EventName == type) ?? false); + + return eventType ?? typeof(object); + } + public object TypedContent { get { try { @@ -21,8 +32,9 @@ public class StateEvent { } catch (JsonException e) { Console.WriteLine(e); - Console.WriteLine("Content:\n"+ObjectExtensions.ToJson(RawContent)); + Console.WriteLine("Content:\n" + ObjectExtensions.ToJson(RawContent)); } + return null; } set => RawContent = JsonSerializer.Deserialize<JsonObject>(JsonSerializer.Serialize(value)); @@ -65,12 +77,7 @@ public class StateEvent { [JsonIgnore] public Type GetType { get { - if (Type == "m.receipt") { - return typeof(Dictionary<string, JsonObject>); - } - - var type = KnownStateEventTypes.FirstOrDefault(x => - x.GetCustomAttributes<MatrixEventAttribute>()?.Any(y => y.EventName == Type) ?? false); + var type = GetStateEventType(Type); //special handling for some types // if (type == typeof(RoomEmotesEventData)) { @@ -94,7 +101,7 @@ public class StateEvent { // } // } - return type ?? typeof(object); + return type; } } diff --git a/MatrixRoomUtils.Core/StateEventStruct.cs b/MatrixRoomUtils.Core/StateEventStruct.cs deleted file mode 100644
index cd301ac..0000000 --- a/MatrixRoomUtils.Core/StateEventStruct.cs +++ /dev/null
@@ -1,12 +0,0 @@ -namespace MatrixRoomUtils.Core; - -public struct StateEventStruct { - public object content { get; set; } - public long origin_server_ts { get; set; } - public string sender { get; set; } - public string state_key { get; set; } - public string type { get; set; } - public string event_id { get; set; } - public string user_id { get; set; } - public string replaces_state { get; set; } -} \ No newline at end of file diff --git a/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs
index 633998c..c263a3a 100644 --- a/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs +++ b/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs
@@ -2,25 +2,25 @@ using System.Text.Json.Serialization; using MatrixRoomUtils.Core.Extensions; using MatrixRoomUtils.Core.Interfaces; -namespace MatrixRoomUtils.Core.StateEventTypes.Common; +namespace MatrixRoomUtils.Core.StateEventTypes.Common; [MatrixEvent(EventName = "im.ponies.room_emotes")] public class RoomEmotesEventData : IStateEventType { [JsonPropertyName("emoticons")] public Dictionary<string, EmoticonData>? Emoticons { get; set; } - + [JsonPropertyName("images")] public Dictionary<string, EmoticonData>? Images { get; set; } - + [JsonPropertyName("pack")] public PackInfo? Pack { get; set; } - + public class EmoticonData { [JsonPropertyName("url")] public string? Url { get; set; } } -} -public class PackInfo { - -} \ No newline at end of file + public class PackInfo { + + } +} diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs
index bab297b..a14e4c5 100644 --- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs +++ b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs
@@ -2,17 +2,27 @@ using System.Text.Json.Serialization; using MatrixRoomUtils.Core.Extensions; using MatrixRoomUtils.Core.Interfaces; -namespace MatrixRoomUtils.Core.StateEventTypes.Spec; +namespace MatrixRoomUtils.Core.StateEventTypes.Spec; [MatrixEvent(EventName = "m.room.avatar")] public class RoomAvatarEventData : IStateEventType { [JsonPropertyName("url")] public string? Url { get; set; } - + [JsonPropertyName("info")] public RoomAvatarInfo? Info { get; set; } public class RoomAvatarInfo { - + [JsonPropertyName("h")] + public int? Height { get; set; } + + [JsonPropertyName("w")] + public int? Width { get; set; } + + [JsonPropertyName("mimetype")] + public string? MimeType { get; set; } + + [JsonPropertyName("size")] + public int? Size { get; set; } } -} \ No newline at end of file +} diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs
index 8b85d69..6127028 100644 --- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs +++ b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs
@@ -2,7 +2,7 @@ using System.Text.Json.Serialization; using MatrixRoomUtils.Core.Extensions; using MatrixRoomUtils.Core.Interfaces; -namespace MatrixRoomUtils.Core.StateEventTypes.Spec; +namespace MatrixRoomUtils.Core.StateEventTypes.Spec; [MatrixEvent(EventName = "m.room.create")] public class RoomCreateEventData : IStateEventType { @@ -16,6 +16,12 @@ public class RoomCreateEventData : IStateEventType { public RoomCreatePredecessor? Predecessor { get; set; } [JsonPropertyName("type")] public string? Type { get; set; } - - public class RoomCreatePredecessor { } -} \ No newline at end of file + + public class RoomCreatePredecessor { + [JsonPropertyName("room_id")] + public string? RoomId { get; set; } + + [JsonPropertyName("event_id")] + public string? EventId { get; set; } + } +} diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/PowerLevelEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs
index 6846db4..1cde660 100644 --- a/MatrixRoomUtils.Core/StateEventTypes/Spec/PowerLevelEventData.cs +++ b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs
@@ -5,7 +5,7 @@ using MatrixRoomUtils.Core.Interfaces; namespace MatrixRoomUtils.Core.StateEventTypes.Spec; [MatrixEvent(EventName = "m.room.power_levels")] -public class PowerLevelEventData : IStateEventType { +public class RoomPowerLevelEventData : IStateEventType { [JsonPropertyName("ban")] public int Ban { get; set; } // = 50; @@ -35,14 +35,22 @@ public class PowerLevelEventData : IStateEventType { [JsonPropertyName("users_default")] public int UsersDefault { get; set; } // = 0; - + [Obsolete("Historical was a key related to MSC2716, a spec change on backfill that was dropped!", true)] [JsonIgnore] [JsonPropertyName("historical")] public int Historical { get; set; } // = 50; - + public class NotificationsPL { [JsonPropertyName("room")] public int Room { get; set; } = 50; } -} \ No newline at end of file + + public bool IsUserAdmin(string userId) { + return Users.TryGetValue(userId, out var level) && level >= Events.Max(x=>x.Value); + } + + public bool UserHasPermission(string userId, string eventType) { + return Users.TryGetValue(userId, out var level) && level >= Events.GetValueOrDefault(eventType, EventsDefault); + } +}