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/AuthenticatedHomeServer.cs175
-rw-r--r--MatrixRoomUtils.Core/EventIdResponse.cs8
-rw-r--r--MatrixRoomUtils.Core/Extensions/ClassCollector.cs22
-rw-r--r--MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs33
-rw-r--r--MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs76
-rw-r--r--MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs9
-rw-r--r--MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs151
-rw-r--r--MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs16
-rw-r--r--MatrixRoomUtils.Core/Extensions/StringExtensions.cs13
-rw-r--r--MatrixRoomUtils.Core/Filters/LocalRoomQueryFilter.cs28
-rw-r--r--MatrixRoomUtils.Core/Filters/SyncFilter.cs66
-rw-r--r--MatrixRoomUtils.Core/Helpers/MediaResolver.cs6
-rw-r--r--MatrixRoomUtils.Core/Helpers/SyncHelper.cs238
-rw-r--r--MatrixRoomUtils.Core/Interfaces/IHomeServer.cs31
-rw-r--r--MatrixRoomUtils.Core/Interfaces/IStateEventType.cs5
-rw-r--r--MatrixRoomUtils.Core/Interfaces/Services/IStorageProvider.cs58
-rw-r--r--MatrixRoomUtils.Core/MatrixException.cs59
-rw-r--r--MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj14
-rw-r--r--MatrixRoomUtils.Core/MessagesResponse.cs19
-rw-r--r--MatrixRoomUtils.Core/RemoteHomeServer.cs16
-rw-r--r--MatrixRoomUtils.Core/Responses/Admin/AdminRoomDeleteRequest.cs18
-rw-r--r--MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs64
-rw-r--r--MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs76
-rw-r--r--MatrixRoomUtils.Core/Responses/CreationContentBaseType.cs18
-rw-r--r--MatrixRoomUtils.Core/Responses/LoginResponse.cs17
-rw-r--r--MatrixRoomUtils.Core/Responses/StateEventResponse.cs48
-rw-r--r--MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs187
-rw-r--r--MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs28
-rw-r--r--MatrixRoomUtils.Core/Services/HomeserverProviderService.cs97
-rw-r--r--MatrixRoomUtils.Core/Services/HomeserverResolverService.cs87
-rw-r--r--MatrixRoomUtils.Core/Services/ServiceInstaller.cs30
-rw-r--r--MatrixRoomUtils.Core/Services/TieredStorageService.cs13
-rw-r--r--MatrixRoomUtils.Core/StateEvent.cs120
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Common/MjolnirShortcodeEventData.cs11
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs26
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/CanonicalAliasEventData.cs13
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/GuestAccessEventData.cs16
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/HistoryVisibilityEventData.cs11
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/JoinRulesEventData.cs18
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/PolicyRuleStateEventData.cs56
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/PresenceStateEventData.cs17
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/ProfileResponseEventData.cs13
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAliasEventData.cs11
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs28
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs27
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomEncryptionEventData.cs15
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMemberEventData.cs29
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMessageEventData.cs19
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomNameEventData.cs11
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPinnedEventData.cs11
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs56
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTopicEventData.cs12
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTypingEventData.cs11
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/ServerACLEventData.cs17
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceChildEventData.cs15
-rw-r--r--MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceParentEventData.cs14
-rw-r--r--MatrixRoomUtils.Core/UserIdAndReason.cs10
57 files changed, 0 insertions, 2313 deletions
diff --git a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
deleted file mode 100644
index fbbb99f..0000000
--- a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-using System.Net.Http.Headers;
-using System.Net.Http.Json;
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Filters;
-using MatrixRoomUtils.Core.Helpers;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
-using MatrixRoomUtils.Core.Responses.Admin;
-using MatrixRoomUtils.Core.RoomTypes;
-using MatrixRoomUtils.Core.Services;
-
-namespace MatrixRoomUtils.Core;
-
-public class AuthenticatedHomeServer : IHomeServer {
-    private readonly TieredStorageService _storage;
-    public readonly HomeserverAdminApi Admin;
-    public readonly SyncHelper SyncHelper;
-
-    public AuthenticatedHomeServer(TieredStorageService storage, string canonicalHomeServerDomain, string accessToken) {
-        _storage = storage;
-        AccessToken = accessToken.Trim();
-        HomeServerDomain = canonicalHomeServerDomain.Trim();
-        Admin = new HomeserverAdminApi(this);
-        SyncHelper = new SyncHelper(this, storage);
-        _httpClient = new MatrixHttpClient();
-    }
-
-    public WhoAmIResponse WhoAmI { get; set; } = null!;
-    public string UserId => WhoAmI.UserId;
-    public string AccessToken { get; set; }
-
-
-    public async Task<GenericRoom> GetRoom(string roomId) => new(this, roomId);
-
-    public async Task<List<GenericRoom>> GetJoinedRooms() {
-        var rooms = new List<GenericRoom>();
-        var roomQuery = await _httpClient.GetAsync("/_matrix/client/v3/joined_rooms");
-
-        var roomsJson = await roomQuery.Content.ReadFromJsonAsync<JsonElement>();
-        foreach (var room in roomsJson.GetProperty("joined_rooms").EnumerateArray()) rooms.Add(new GenericRoom(this, room.GetString()));
-
-        Console.WriteLine($"Fetched {rooms.Count} rooms");
-
-        return rooms;
-    }
-
-    public async Task<string> UploadFile(string fileName, Stream fileStream, string contentType = "application/octet-stream") {
-        var res = await _httpClient.PostAsync($"/_matrix/media/v3/upload?filename={fileName}", new StreamContent(fileStream));
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to upload file: {await res.Content.ReadAsStringAsync()}");
-            throw new InvalidDataException($"Failed to upload file: {await res.Content.ReadAsStringAsync()}");
-        }
-
-        var resJson = await res.Content.ReadFromJsonAsync<JsonElement>();
-        return resJson.GetProperty("content_uri").GetString()!;
-    }
-
-    public async Task<GenericRoom> CreateRoom(CreateRoomRequest creationEvent) {
-        var res = await _httpClient.PostAsJsonAsync("/_matrix/client/v3/createRoom", creationEvent);
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to create room: {await res.Content.ReadAsStringAsync()}");
-            throw new InvalidDataException($"Failed to create room: {await res.Content.ReadAsStringAsync()}");
-        }
-
-        return await GetRoom((await res.Content.ReadFromJsonAsync<JsonObject>())!["room_id"]!.ToString());
-    }
-
-    public class HomeserverAdminApi {
-        private readonly AuthenticatedHomeServer _authenticatedHomeServer;
-
-        public HomeserverAdminApi(AuthenticatedHomeServer authenticatedHomeServer) => _authenticatedHomeServer = authenticatedHomeServer;
-
-        public async IAsyncEnumerable<AdminRoomListingResult.AdminRoomListingResultRoom> SearchRoomsAsync(int limit = int.MaxValue, string orderBy = "name", string dir = "f", string? searchTerm = null, LocalRoomQueryFilter? localFilter = null) {
-            AdminRoomListingResult? res = null;
-            var i = 0;
-            int? totalRooms = null;
-            do {
-                var url = $"/_synapse/admin/v1/rooms?limit={Math.Min(limit, 100)}&dir={dir}&order_by={orderBy}";
-                if (!string.IsNullOrEmpty(searchTerm)) url += $"&search_term={searchTerm}";
-
-                if (res?.NextBatch is not null) url += $"&from={res.NextBatch}";
-
-                Console.WriteLine($"--- ADMIN Querying Room List with URL: {url} - Already have {i} items... ---");
-
-                res = await _authenticatedHomeServer._httpClient.GetFromJsonAsync<AdminRoomListingResult>(url);
-                totalRooms ??= res?.TotalRooms;
-                Console.WriteLine(res.ToJson(false));
-                foreach (var room in res.Rooms) {
-                    if (localFilter is not null) {
-                        if (!room.RoomId.Contains(localFilter.RoomIdContains)) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if (!room.Name?.Contains(localFilter.NameContains) == true) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if (!room.CanonicalAlias?.Contains(localFilter.CanonicalAliasContains) == true) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if (!room.Version.Contains(localFilter.VersionContains)) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if (!room.Creator.Contains(localFilter.CreatorContains)) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if (!room.Encryption?.Contains(localFilter.EncryptionContains) == true) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if (!room.JoinRules?.Contains(localFilter.JoinRulesContains) == true) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if(!room.GuestAccess?.Contains(localFilter.GuestAccessContains) == true) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if(!room.HistoryVisibility?.Contains(localFilter.HistoryVisibilityContains) == true) {
-                            totalRooms--;
-                            continue;
-                        }
-                        
-                        if(localFilter.CheckFederation && room.Federatable != localFilter.Federatable) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if(localFilter.CheckPublic && room.Public != localFilter.Public) {
-                            totalRooms--;
-                            continue;
-                        }
-                        
-                        if(room.JoinedMembers < localFilter.JoinedMembersGreaterThan || room.JoinedMembers > localFilter.JoinedMembersLessThan) {
-                            totalRooms--;
-                            continue;
-                        }
-                        if(room.JoinedLocalMembers < localFilter.JoinedLocalMembersGreaterThan || room.JoinedLocalMembers > localFilter.JoinedLocalMembersLessThan) {
-                            totalRooms--;
-                            continue;
-                        }
-                    }
-                    // if (contentSearch is not null && !string.IsNullOrEmpty(contentSearch) &&
-                    //     !(
-                    //         room.Name?.Contains(contentSearch, StringComparison.InvariantCultureIgnoreCase) == true ||
-                    //         room.CanonicalAlias?.Contains(contentSearch, StringComparison.InvariantCultureIgnoreCase) == true ||
-                    //         room.Creator?.Contains(contentSearch, StringComparison.InvariantCultureIgnoreCase) == true
-                    //     )
-                    //    ) {
-                    //     totalRooms--;
-                    //     continue;
-                    // }
-
-                    i++;
-                    yield return room;
-                }
-            } while (i < Math.Min(limit, totalRooms ?? limit));
-        }
-    }
-}
-
-public class WhoAmIResponse {
-    [JsonPropertyName("user_id")]
-    public string UserId { get; set; } = null!;
-
-    [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/MatrixRoomUtils.Core/EventIdResponse.cs b/MatrixRoomUtils.Core/EventIdResponse.cs
deleted file mode 100644
index 77dc7f8..0000000
--- a/MatrixRoomUtils.Core/EventIdResponse.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core;
-
-public class EventIdResponse {
-    [JsonPropertyName("event_id")]
-    public string EventId { get; set; } = null!;
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/ClassCollector.cs b/MatrixRoomUtils.Core/Extensions/ClassCollector.cs
deleted file mode 100644
index d4ba838..0000000
--- a/MatrixRoomUtils.Core/Extensions/ClassCollector.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System.Reflection;
-
-namespace MatrixRoomUtils.Core.Extensions;
-
-public class ClassCollector<T> where T : class {
-    static ClassCollector() {
-        if (!typeof(T).IsInterface)
-            throw new ArgumentException(
-                $"ClassCollector<T> must be used with an interface type. Passed type: {typeof(T).Name}");
-    }
-
-    public List<Type> ResolveFromAllAccessibleAssemblies() => AppDomain.CurrentDomain.GetAssemblies().SelectMany(ResolveFromAssembly).ToList();
-
-    public List<Type> ResolveFromObjectReference(object obj) => ResolveFromTypeReference(obj.GetType());
-
-    public List<Type> ResolveFromTypeReference(Type t) => Assembly.GetAssembly(t)?.GetReferencedAssemblies().SelectMany(ResolveFromAssemblyName).ToList() ?? new List<Type>();
-
-    public List<Type> ResolveFromAssemblyName(AssemblyName assemblyName) => ResolveFromAssembly(Assembly.Load(assemblyName));
-
-    public List<Type> ResolveFromAssembly(Assembly assembly) => assembly.GetTypes()
-        .Where(x => x is { IsClass: true, IsAbstract: false } && x.GetInterfaces().Contains(typeof(T))).ToList();
-}
diff --git a/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs b/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs
deleted file mode 100644
index 78bbdfa..0000000
--- a/MatrixRoomUtils.Core/Extensions/DictionaryExtensions.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-namespace MatrixRoomUtils.Core.Extensions;
-
-public static class DictionaryExtensions {
-    public static bool ChangeKey<TKey, TValue>(this IDictionary<TKey, TValue> dict,
-        TKey oldKey, TKey newKey) {
-        TValue value;
-        if (!dict.Remove(oldKey, out value))
-            return false;
-
-        dict[newKey] = value; // or dict.Add(newKey, value) depending on ur comfort
-        return true;
-    }
-
-    public static Y GetOrCreate<X, Y>(this IDictionary<X, Y> dict, X key) where Y : new() {
-        if (dict.TryGetValue(key, out var value)) {
-            return value;
-        }
-
-        value = new Y();
-        dict.Add(key, value);
-        return value;
-    }
-
-    public static Y GetOrCreate<X, Y>(this IDictionary<X, Y> dict, X key, Func<X, Y> valueFactory) {
-        if (dict.TryGetValue(key, out var value)) {
-            return value;
-        }
-
-        value = valueFactory(key);
-        dict.Add(key, value);
-        return value;
-    }
-}
diff --git a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
deleted file mode 100644
index 009338a..0000000
--- a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System.Net.Http.Headers;
-using System.Reflection;
-using System.Text.Json;
-
-namespace MatrixRoomUtils.Core.Extensions;
-
-public static class HttpClientExtensions {
-    public static async Task<bool> CheckSuccessStatus(this HttpClient hc, string url) {
-        //cors causes failure, try to catch
-        try {
-            var resp = await hc.GetAsync(url);
-            return resp.IsSuccessStatusCode;
-        }
-        catch (Exception e) {
-            Console.WriteLine($"Failed to check success status: {e.Message}");
-            return false;
-        }
-    }
-}
-
-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");
-            request.Options.Set(WebAssemblyEnableStreamingResponseKey, true);
-        }
-        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}");
-                if (ex?.RetryAfterMs is not null) {
-                    await Task.Delay(ex.RetryAfterMs.Value, cancellationToken);
-                    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);
-        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
-        var response = await SendAsync(request, cancellationToken);
-        response.EnsureSuccessStatusCode();
-        await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
-        return await JsonSerializer.DeserializeAsync<T>(responseStream, cancellationToken: cancellationToken);
-    }
-
-    // GetStreamAsync
-    public async Task<Stream> 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);
-        response.EnsureSuccessStatusCode();
-        return await response.Content.ReadAsStreamAsync(cancellationToken);
-    }
-}
diff --git a/MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs b/MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs
deleted file mode 100644
index 8994529..0000000
--- a/MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.Extensions;
-
-[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
-public class MatrixEventAttribute : Attribute {
-    public string EventName { get; set; }
-    public bool Legacy { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
deleted file mode 100644
index 7701c9e..0000000
--- a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-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(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;
-        }
-
-        return unknownPropertyFound;
-    }
-
-    private static bool FindExtraJsonPropertyFieldsByValueKind(this JsonProperty field, Type containerType,
-        Type propertyType) {
-        if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
-            propertyType = propertyType.GetGenericArguments()[0];
-        }
-
-        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 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)
-            );
-    }
-}
diff --git a/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs b/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
deleted file mode 100644
index a4b0791..0000000
--- a/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Text.Encodings.Web;
-using System.Text.Json;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
-
-namespace MatrixRoomUtils.Core.Extensions;
-
-public static class ObjectExtensions {
-    public static string ToJson(this object obj, bool indent = true, bool ignoreNull = false, bool unsafeContent = false) {
-        var jso = new JsonSerializerOptions();
-        if (indent) jso.WriteIndented = true;
-        if (ignoreNull) jso.IgnoreNullValues = true;
-        if (unsafeContent) jso.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
-        return JsonSerializer.Serialize(obj, jso);
-    }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/StringExtensions.cs b/MatrixRoomUtils.Core/Extensions/StringExtensions.cs
deleted file mode 100644
index b81d59f..0000000
--- a/MatrixRoomUtils.Core/Extensions/StringExtensions.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace MatrixRoomUtils.Core.Extensions;
-
-public static class StringExtensions {
-    // public static async Task<string> GetMediaUrl(this string MxcUrl)
-    // {
-    //     //MxcUrl: mxc://rory.gay/ocRVanZoUTCcifcVNwXgbtTg
-    //     //target: https://matrix.rory.gay/_matrix/media/v3/download/rory.gay/ocRVanZoUTCcifcVNwXgbtTg
-    //     
-    //     var server = MxcUrl.Split('/')[2];
-    //     var mediaId = MxcUrl.Split('/')[3];
-    //     return $"{(await new RemoteHomeServer(server).Configure()).FullHomeServerDomain}/_matrix/media/v3/download/{server}/{mediaId}";
-    // }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Filters/LocalRoomQueryFilter.cs b/MatrixRoomUtils.Core/Filters/LocalRoomQueryFilter.cs
deleted file mode 100644
index 65c7baa..0000000
--- a/MatrixRoomUtils.Core/Filters/LocalRoomQueryFilter.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace MatrixRoomUtils.Core.Filters;
-
-public class LocalRoomQueryFilter {
-    public string RoomIdContains { get; set; } = "";
-    public string NameContains { get; set; } = "";
-    public string CanonicalAliasContains { get; set; } = "";
-    public string VersionContains { get; set; } = "";
-    public string CreatorContains { get; set; } = "";
-    public string EncryptionContains { get; set; } = "";
-    public string JoinRulesContains { get; set; } = "";
-    public string GuestAccessContains { get; set; } = "";
-    public string HistoryVisibilityContains { get; set; } = "";
-    
-    public bool Federatable { get; set; } = true;
-    public bool Public { get; set; } = true;
-    
-    public int JoinedMembersGreaterThan { get; set; } = 0;
-    public int JoinedMembersLessThan { get; set; } = int.MaxValue;
-
-    public int JoinedLocalMembersGreaterThan { get; set; } = 0;
-    public int JoinedLocalMembersLessThan { get; set; } = int.MaxValue;
-    public int StateEventsGreaterThan { get; set; } = 0;
-    public int StateEventsLessThan { get; set; } = int.MaxValue;
-
-    
-    public bool CheckFederation { get; set; }
-    public bool CheckPublic { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Filters/SyncFilter.cs b/MatrixRoomUtils.Core/Filters/SyncFilter.cs
deleted file mode 100644
index bc81101..0000000
--- a/MatrixRoomUtils.Core/Filters/SyncFilter.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core.Filters;
-
-public class SyncFilter {
-    [JsonPropertyName("account_data")]
-    public EventFilter? AccountData { get; set; }
-
-    [JsonPropertyName("presence")]
-    public EventFilter? Presence { get; set; }
-
-    [JsonPropertyName("room")]
-    public RoomFilter? Room { get; set; }
-
-    public class RoomFilter {
-        [JsonPropertyName("account_data")]
-        public StateFilter? AccountData { get; set; }
-
-        [JsonPropertyName("ephemeral")]
-        public StateFilter? Ephemeral { get; set; }
-
-        [JsonPropertyName("state")]
-        public StateFilter? State { get; set; }
-
-        [JsonPropertyName("timeline")]
-        public StateFilter? Timeline { get; set; }
-
-
-        public class StateFilter : EventFilter {
-            [JsonPropertyName("contains_url")]
-            public bool? ContainsUrl { 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("unread_thread_notifications")]
-            public bool? UnreadThreadNotifications { get; set; }
-        }
-    }
-
-    public class EventFilter {
-        [JsonPropertyName("limit")]
-        public int? Limit { get; set; }
-
-        [JsonPropertyName("types")]
-        public List<string>? Types { get; set; }
-
-        [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; }
-    }
-}
diff --git a/MatrixRoomUtils.Core/Helpers/MediaResolver.cs b/MatrixRoomUtils.Core/Helpers/MediaResolver.cs
deleted file mode 100644
index 0869135..0000000
--- a/MatrixRoomUtils.Core/Helpers/MediaResolver.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace MatrixRoomUtils.Core.Helpers; 
-
-public class MediaResolver {
-    public static string ResolveMediaUri(string homeserver, string mxc) => 
-        mxc.Replace("mxc://", $"{homeserver}/_matrix/media/v3/download/");
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Helpers/SyncHelper.cs b/MatrixRoomUtils.Core/Helpers/SyncHelper.cs
deleted file mode 100644
index e12164c..0000000
--- a/MatrixRoomUtils.Core/Helpers/SyncHelper.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Net.Http.Json;
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Filters;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
-using MatrixRoomUtils.Core.Responses.Admin;
-using MatrixRoomUtils.Core.Services;
-using MatrixRoomUtils.Core.StateEventTypes;
-
-namespace MatrixRoomUtils.Core.Helpers;
-
-public class SyncHelper {
-    private readonly AuthenticatedHomeServer _homeServer;
-    private readonly TieredStorageService _storageService;
-
-    public SyncHelper(AuthenticatedHomeServer homeServer, TieredStorageService storageService) {
-        _homeServer = homeServer;
-        _storageService = storageService;
-    }
-
-    public async Task<SyncResult?> Sync(
-        string? since = null,
-        int? timeout = 30000,
-        string? setPresence = "online",
-        SyncFilter? filter = null,
-        CancellationToken? cancellationToken = null) {
-        var outFileName = "sync-" +
-                          (await _storageService.CacheStorageProvider.GetAllKeysAsync()).Count(
-                              x => x.StartsWith("sync")) +
-                          ".json";
-        var url = $"/_matrix/client/v3/sync?timeout={timeout}&set_presence={setPresence}";
-        if (!string.IsNullOrWhiteSpace(since)) url += $"&since={since}";
-        if (filter is not null) url += $"&filter={filter.ToJson(ignoreNull: true, indent: false)}";
-        // else url += "&full_state=true";
-        Console.WriteLine("Calling: " + url);
-        try {
-            var req = await _homeServer._httpClient.GetAsync(url, cancellationToken: cancellationToken ?? CancellationToken.None);
-
-            // var res = await JsonSerializer.DeserializeAsync<SyncResult>(await req.Content.ReadAsStreamAsync());
-
-#if DEBUG && false
-            var jsonObj = await req.Content.ReadFromJsonAsync<JsonElement>();
-            try {
-                await _homeServer._httpClient.PostAsJsonAsync(
-                    "http://localhost:5116/validate/" + typeof(SyncResult).AssemblyQualifiedName, jsonObj);
-            }
-            catch (Exception e) {
-                Console.WriteLine("[!!] Checking sync response failed: " + e);
-            }
-
-            var res = jsonObj.Deserialize<SyncResult>();
-            return res;
-#else
-            return await req.Content.ReadFromJsonAsync<SyncResult>();
-#endif
-        }
-        catch (TaskCanceledException) {
-            Console.WriteLine("Sync cancelled!");
-        }
-        catch (Exception e) {
-            Console.WriteLine(e);
-        }
-
-        return null;
-    }
-
-    [SuppressMessage("ReSharper", "FunctionNeverReturns")]
-    public async Task RunSyncLoop(
-        bool skipInitialSyncEvents = true,
-        string? since = null,
-        int? timeout = 30000,
-        string? setPresence = "online",
-        SyncFilter? filter = null,
-        CancellationToken? cancellationToken = null
-    ) {
-        await Task.WhenAll((await _storageService.CacheStorageProvider.GetAllKeysAsync())
-            .Where(x => x.StartsWith("sync"))
-            .ToList()
-            .Select(x => _storageService.CacheStorageProvider.DeleteObjectAsync(x)));
-        SyncResult? sync = null;
-        string? nextBatch = since;
-        while (cancellationToken is null || !cancellationToken.Value.IsCancellationRequested) {
-            sync = await Sync(since: nextBatch, timeout: timeout, setPresence: setPresence, filter: filter,
-                cancellationToken: cancellationToken);
-            nextBatch = sync?.NextBatch ?? nextBatch;
-            if (sync is null) continue;
-            Console.WriteLine($"Got sync, next batch: {nextBatch}!");
-
-            if (sync.Rooms is { Invite.Count: > 0 }) {
-                foreach (var roomInvite in sync.Rooms.Invite) {
-                    var tasks = InviteReceivedHandlers.Select(x => x(roomInvite)).ToList();
-                    await Task.WhenAll(tasks);
-                }
-            }
-
-            if (sync.AccountData is { Events: { Count: > 0 } }) {
-                foreach (var accountDataEvent in sync.AccountData.Events) {
-                    var tasks = AccountDataReceivedHandlers.Select(x => x(accountDataEvent)).ToList();
-                    await Task.WhenAll(tasks);
-                }
-            }
-
-            // Things that are skipped on the first sync
-            if (skipInitialSyncEvents) {
-                skipInitialSyncEvents = false;
-                continue;
-            }
-
-            if (sync.Rooms is { Join.Count: > 0 }) {
-                foreach (var updatedRoom in sync.Rooms.Join) {
-                    foreach (var stateEventResponse in updatedRoom.Value.Timeline.Events) {
-                        stateEventResponse.RoomId = updatedRoom.Key;
-                        var tasks = TimelineEventHandlers.Select(x => x(stateEventResponse)).ToList();
-                        await Task.WhenAll(tasks);
-                    }
-                }
-            }
-        }
-    }
-
-    /// <summary>
-    /// Event fired when a room invite is received
-    /// </summary>
-    public List<Func<KeyValuePair<string, SyncResult.RoomsDataStructure.InvitedRoomDataStructure>, Task>>
-        InviteReceivedHandlers { get; } = new();
-
-    public List<Func<StateEventResponse, Task>> TimelineEventHandlers { get; } = new();
-    public List<Func<StateEventResponse, Task>> AccountDataReceivedHandlers { get; } = new();
-}
-
-public class SyncResult {
-    [JsonPropertyName("next_batch")]
-    public string NextBatch { get; set; }
-
-    [JsonPropertyName("account_data")]
-    public EventList? AccountData { get; set; }
-
-    [JsonPropertyName("presence")]
-    public PresenceDataStructure? Presence { get; set; }
-
-    [JsonPropertyName("device_one_time_keys_count")]
-    public Dictionary<string, int> DeviceOneTimeKeysCount { get; set; }
-
-    [JsonPropertyName("rooms")]
-    public RoomsDataStructure? Rooms { get; set; }
-
-    [JsonPropertyName("to_device")]
-    public EventList? ToDevice { get; set; }
-
-    [JsonPropertyName("device_lists")]
-    public DeviceListsDataStructure? DeviceLists { get; set; }
-
-    public class DeviceListsDataStructure {
-        [JsonPropertyName("changed")]
-        public List<string>? Changed { get; set; }
-
-        [JsonPropertyName("left")]
-        public List<string>? Left { get; set; }
-    }
-
-    // supporting classes
-    public class PresenceDataStructure {
-        [JsonPropertyName("events")]
-        public List<StateEventResponse> Events { get; set; }
-    }
-
-    public class RoomsDataStructure {
-        [JsonPropertyName("join")]
-        public Dictionary<string, JoinedRoomDataStructure>? Join { get; set; }
-
-        [JsonPropertyName("invite")]
-        public Dictionary<string, InvitedRoomDataStructure>? Invite { get; set; }
-
-        public class JoinedRoomDataStructure {
-            [JsonPropertyName("timeline")]
-            public TimelineDataStructure Timeline { get; set; }
-
-            [JsonPropertyName("state")]
-            public EventList State { get; set; }
-
-            [JsonPropertyName("account_data")]
-            public EventList AccountData { get; set; }
-
-            [JsonPropertyName("ephemeral")]
-            public EventList Ephemeral { get; set; }
-
-            [JsonPropertyName("unread_notifications")]
-            public UnreadNotificationsDataStructure UnreadNotifications { get; set; }
-
-            [JsonPropertyName("summary")]
-            public SummaryDataStructure Summary { get; set; }
-
-            public class TimelineDataStructure {
-                [JsonPropertyName("events")]
-                public List<StateEventResponse> Events { get; set; }
-
-                [JsonPropertyName("prev_batch")]
-                public string PrevBatch { get; set; }
-
-                [JsonPropertyName("limited")]
-                public bool Limited { get; set; }
-            }
-
-            public class UnreadNotificationsDataStructure {
-                [JsonPropertyName("notification_count")]
-                public int NotificationCount { get; set; }
-
-                [JsonPropertyName("highlight_count")]
-                public int HighlightCount { get; set; }
-            }
-
-            public class SummaryDataStructure {
-                [JsonPropertyName("m.heroes")]
-                public List<string> Heroes { get; set; }
-
-                [JsonPropertyName("m.invited_member_count")]
-                public int InvitedMemberCount { get; set; }
-
-                [JsonPropertyName("m.joined_member_count")]
-                public int JoinedMemberCount { get; set; }
-            }
-        }
-
-        public class InvitedRoomDataStructure {
-            [JsonPropertyName("invite_state")]
-            public EventList InviteState { get; set; }
-        }
-    }
-}
-
-public class EventList {
-    [JsonPropertyName("events")]
-    public List<StateEventResponse> Events { get; set; }
-}
diff --git a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
deleted file mode 100644
index 3521a51..0000000
--- a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Net.Http.Json;
-using System.Text.Json;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.StateEventTypes;
-using MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-namespace MatrixRoomUtils.Core.Interfaces;
-
-public class IHomeServer {
-    private readonly Dictionary<string, object> _profileCache = new();
-    public string HomeServerDomain { get; set; }
-    public string FullHomeServerDomain { get; set; }
-
-    public MatrixHttpClient _httpClient { get; set; } = new();
-
-    public async Task<ProfileResponseEventData> GetProfile(string mxid) {
-        if(mxid is null) throw new ArgumentNullException(nameof(mxid));
-        if (_profileCache.ContainsKey(mxid)) {
-            if (_profileCache[mxid] is SemaphoreSlim s) await s.WaitAsync();
-            if (_profileCache[mxid] is ProfileResponseEventData p) return p;
-        }
-        _profileCache[mxid] = new SemaphoreSlim(1);
-
-        var resp = await _httpClient.GetAsync($"/_matrix/client/v3/profile/{mxid}");
-        var data = await resp.Content.ReadFromJsonAsync<ProfileResponseEventData>();
-        if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data);
-        _profileCache[mxid] = data;
-
-        return data;
-    }
-}
diff --git a/MatrixRoomUtils.Core/Interfaces/IStateEventType.cs b/MatrixRoomUtils.Core/Interfaces/IStateEventType.cs
deleted file mode 100644
index 053f50c..0000000
--- a/MatrixRoomUtils.Core/Interfaces/IStateEventType.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace MatrixRoomUtils.Core.Interfaces; 
-
-public interface IStateEventType {
-    
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Interfaces/Services/IStorageProvider.cs b/MatrixRoomUtils.Core/Interfaces/Services/IStorageProvider.cs
deleted file mode 100644
index 1de9885..0000000
--- a/MatrixRoomUtils.Core/Interfaces/Services/IStorageProvider.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-namespace MatrixRoomUtils.Core.Interfaces.Services;
-
-public interface IStorageProvider {
-    // save all children of a type with reflection
-    public Task SaveAllChildrenAsync<T>(string key, T value) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement SaveAllChildren<T>(key, value)!");
-        throw new NotImplementedException();
-    }
-
-    // load all children of a type with reflection
-    public Task<T?> LoadAllChildrenAsync<T>(string key) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement LoadAllChildren<T>(key)!");
-        throw new NotImplementedException();
-    }
-
-
-    public Task SaveObjectAsync<T>(string key, T value) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement SaveObject<T>(key, value)!");
-        throw new NotImplementedException();
-    }
-
-    // load
-    public Task<T?> LoadObjectAsync<T>(string key) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement LoadObject<T>(key)!");
-        throw new NotImplementedException();
-    }
-
-    // check if exists
-    public Task<bool> ObjectExistsAsync(string key) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement ObjectExists(key)!");
-        throw new NotImplementedException();
-    }
-
-    // get all keys
-    public Task<List<string>> GetAllKeysAsync() {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement GetAllKeys()!");
-        throw new NotImplementedException();
-    }
-
-
-    // delete
-    public Task DeleteObjectAsync(string key) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement DeleteObject(key)!");
-        throw new NotImplementedException();
-    }
-
-    // save stream
-    public Task SaveStreamAsync(string key, Stream stream) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement SaveStream(key, stream)!");
-        throw new NotImplementedException();
-    }
-
-    // load stream
-    public Task<Stream?> LoadStreamAsync(string key) {
-        Console.WriteLine($"StorageProvider<{GetType().Name}> does not implement LoadStream(key)!");
-        throw new NotImplementedException();
-    }
-}
diff --git a/MatrixRoomUtils.Core/MatrixException.cs b/MatrixRoomUtils.Core/MatrixException.cs
deleted file mode 100644
index a469a62..0000000
--- a/MatrixRoomUtils.Core/MatrixException.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-
-namespace MatrixRoomUtils.Core;
-
-public class MatrixException : Exception {
-    [JsonPropertyName("errcode")]
-    public string ErrorCode { get; set; }
-
-    [JsonPropertyName("error")]
-    public string Error { get; set; }
-
-    [JsonPropertyName("soft_logout")]
-    public bool? SoftLogout { get; set; }
-
-    [JsonPropertyName("retry_after_ms")]
-    public int? RetryAfterMs { get; set; }
-
-    public string RawContent { get; set; }
-
-    public override string Message =>
-        $"{ErrorCode}: {ErrorCode switch {
-            // common
-            "M_FORBIDDEN" => $"You do not have permission to perform this action: {Error}",
-            "M_UNKNOWN_TOKEN" => $"The access token specified was not recognised: {Error}{(SoftLogout == true ? " (soft logout)" : "")}",
-            "M_MISSING_TOKEN" => $"No access token was specified: {Error}",
-            "M_BAD_JSON" => $"Request contained valid JSON, but it was malformed in some way: {Error}",
-            "M_NOT_JSON" => $"Request did not contain valid JSON: {Error}",
-            "M_NOT_FOUND" => $"The requested resource was not found: {Error}",
-            "M_LIMIT_EXCEEDED" => $"Too many requests have been sent in a short period of time. Wait a while then try again: {Error}",
-            "M_UNRECOGNISED" => $"The server did not recognise the request: {Error}",
-            "M_UNKOWN" => $"The server encountered an unexpected error: {Error}",
-            // endpoint specific
-            "M_UNAUTHORIZED" => $"The request did not contain valid authentication information for the target of the request: {Error}",
-            "M_USER_DEACTIVATED" => $"The user ID associated with the request has been deactivated: {Error}",
-            "M_USER_IN_USE" => $"The user ID associated with the request is already in use: {Error}",
-            "M_INVALID_USERNAME" => $"The requested user ID is not valid: {Error}",
-            "M_ROOM_IN_USE" => $"The room alias requested is already taken: {Error}",
-            "M_INVALID_ROOM_STATE" => $"The room associated with the request is not in a valid state to perform the request: {Error}",
-            "M_THREEPID_IN_USE" => $"The threepid requested is already associated with a user ID on this server: {Error}",
-            "M_THREEPID_NOT_FOUND" => $"The threepid requested is not associated with any user ID: {Error}",
-            "M_THREEPID_AUTH_FAILED" => $"The provided threepid and/or token was invalid: {Error}",
-            "M_THREEPID_DENIED" => $"The homeserver does not permit the third party identifier in question: {Error}",
-            "M_SERVER_NOT_TRUSTED" => $"The homeserver does not trust the identity server: {Error}",
-            "M_UNSUPPORTED_ROOM_VERSION" => $"The room version is not supported: {Error}",
-            "M_INCOMPATIBLE_ROOM_VERSION" => $"The room version is incompatible: {Error}",
-            "M_BAD_STATE" => $"The request was invalid because the state was invalid: {Error}",
-            "M_GUEST_ACCESS_FORBIDDEN" => $"Guest access is forbidden: {Error}",
-            "M_CAPTCHA_NEEDED" => $"Captcha needed: {Error}",
-            "M_CAPTCHA_INVALID" => $"Captcha invalid: {Error}",
-            "M_MISSING_PARAM" => $"Missing parameter: {Error}",
-            "M_INVALID_PARAM" => $"Invalid parameter: {Error}",
-            "M_TOO_LARGE" => $"The request or entity was too large: {Error}",
-            "M_EXCLUSIVE" => $"The resource being requested is reserved by an application service, or the application service making the request has not created the resource: {Error}",
-            "M_RESOURCE_LIMIT_EXCEEDED" => $"Exceeded resource limit: {Error}",
-            "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM" => $"Cannot leave server notice room: {Error}",
-            _ => $"Unknown error: {new { ErrorCode, Error, SoftLogout, RetryAfterMs }.ToJson(ignoreNull: true)}"
-        }}";
-}
diff --git a/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj b/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj
deleted file mode 100644
index 3571eab..0000000
--- a/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj
+++ /dev/null
@@ -1,14 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>net7.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-    </PropertyGroup>
-
-    <ItemGroup>
-        <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
-        <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
-    </ItemGroup>
-
-</Project>
diff --git a/MatrixRoomUtils.Core/MessagesResponse.cs b/MatrixRoomUtils.Core/MessagesResponse.cs
deleted file mode 100644
index 7a303bc..0000000
--- a/MatrixRoomUtils.Core/MessagesResponse.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
-
-namespace MatrixRoomUtils.Core;
-
-public class MessagesResponse {
-    [JsonPropertyName("start")]
-    public string Start { get; set; }
-
-    [JsonPropertyName("end")]
-    public string? End { get; set; }
-
-    [JsonPropertyName("chunk")]
-    public List<StateEventResponse> Chunk { get; set; } = new();
-
-    [JsonPropertyName("state")]
-    public List<StateEventResponse> State { get; set; } = new();
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RemoteHomeServer.cs b/MatrixRoomUtils.Core/RemoteHomeServer.cs
deleted file mode 100644
index e6c28c3..0000000
--- a/MatrixRoomUtils.Core/RemoteHomeServer.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Net.Http.Json;
-using System.Text.Json;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Services;
-
-namespace MatrixRoomUtils.Core;
-
-public class RemoteHomeServer : IHomeServer {
-    public RemoteHomeServer(string canonicalHomeServerDomain) {
-        HomeServerDomain = canonicalHomeServerDomain;
-        _httpClient = new MatrixHttpClient();
-        _httpClient.Timeout = TimeSpan.FromSeconds(5);
-    }
-
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/Admin/AdminRoomDeleteRequest.cs b/MatrixRoomUtils.Core/Responses/Admin/AdminRoomDeleteRequest.cs
deleted file mode 100644
index 5605329..0000000
--- a/MatrixRoomUtils.Core/Responses/Admin/AdminRoomDeleteRequest.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core.Responses.Admin; 
-
-public class AdminRoomDeleteRequest {
-    [JsonPropertyName("new_room_user_id")]
-    public string? NewRoomUserId { get; set; }
-    [JsonPropertyName("room_name")]
-    public string? RoomName { get; set; }
-    [JsonPropertyName("block")]
-    public bool Block { get; set; }
-    [JsonPropertyName("purge")]
-    public bool Purge { get; set; }
-    [JsonPropertyName("message")]
-    public string? Message { get; set; }
-    [JsonPropertyName("force_purge")]
-    public bool ForcePurge { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs b/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs
deleted file mode 100644
index d6da859..0000000
--- a/MatrixRoomUtils.Core/Responses/Admin/AdminRoomListingResult.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core.Responses.Admin;
-
-public class AdminRoomListingResult {
-    [JsonPropertyName("offset")]
-    public int Offset { get; set; }
-
-    [JsonPropertyName("total_rooms")]
-    public int TotalRooms { get; set; }
-
-    [JsonPropertyName("next_batch")]
-    public int? NextBatch { get; set; }
-
-    [JsonPropertyName("prev_batch")]
-    public int? PrevBatch { get; set; }
-
-    [JsonPropertyName("rooms")]
-    public List<AdminRoomListingResultRoom> Rooms { get; set; } = new();
-
-    public class AdminRoomListingResultRoom {
-        [JsonPropertyName("room_id")]
-        public string RoomId { get; set; }
-
-        [JsonPropertyName("name")]
-        public string? Name { get; set; }
-
-        [JsonPropertyName("canonical_alias")]
-        public string? CanonicalAlias { get; set; }
-
-        [JsonPropertyName("joined_members")]
-        public int JoinedMembers { get; set; }
-
-        [JsonPropertyName("joined_local_members")]
-        public int JoinedLocalMembers { get; set; }
-
-        [JsonPropertyName("version")]
-        public string Version { get; set; }
-
-        [JsonPropertyName("creator")]
-        public string Creator { get; set; }
-
-        [JsonPropertyName("encryption")]
-        public string? Encryption { get; set; }
-
-        [JsonPropertyName("federatable")]
-        public bool Federatable { get; set; }
-
-        [JsonPropertyName("public")]
-        public bool Public { get; set; }
-
-        [JsonPropertyName("join_rules")]
-        public string? JoinRules { get; set; }
-
-        [JsonPropertyName("guest_access")]
-        public string? GuestAccess { get; set; }
-
-        [JsonPropertyName("history_visibility")]
-        public string? HistoryVisibility { get; set; }
-
-        [JsonPropertyName("state_events")]
-        public int StateEvents { get; set; }
-    }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
deleted file mode 100644
index 540a323..0000000
--- a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System.Reflection;
-using System.Text.Json.Nodes;
-using System.Text.Json.Serialization;
-using System.Text.RegularExpressions;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.StateEventTypes;
-using MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-namespace MatrixRoomUtils.Core.Responses;
-
-public class CreateRoomRequest {
-    [JsonIgnore] public CreationContentBaseType _creationContentBaseType;
-
-    public CreateRoomRequest() => _creationContentBaseType = new CreationContentBaseType(this);
-
-    [JsonPropertyName("name")]
-    public string Name { get; set; } = null!;
-
-    [JsonPropertyName("room_alias_name")]
-    public string RoomAliasName { get; set; } = null!;
-
-    //we dont want to use this, we want more control
-    // [JsonPropertyName("preset")]
-    // public string Preset { get; set; } = null!;
-
-    [JsonPropertyName("initial_state")]
-    public List<StateEvent> InitialState { get; set; } = null!;
-
-    [JsonPropertyName("visibility")]
-    public string Visibility { get; set; } = null!;
-
-    [JsonPropertyName("power_level_content_override")]
-    public RoomPowerLevelEventData PowerLevelContentOverride { get; set; } = null!;
-
-    [JsonPropertyName("creation_content")]
-    public JsonObject CreationContent { get; set; } = new();
-
-    /// <summary>
-    ///     For use only when you can't use the CreationContent property
-    /// </summary>
-
-    public StateEvent this[string event_type, string event_key = ""] {
-        get {
-            var stateEvent = InitialState.FirstOrDefault(x => x.Type == event_type && x.StateKey == event_key);
-            if (stateEvent == null) {
-                InitialState.Add(stateEvent = new StateEvent {
-                    Type = event_type,
-                    StateKey = event_key,
-                    TypedContent = Activator.CreateInstance(
-                        StateEvent.KnownStateEventTypes.FirstOrDefault(x =>
-                            x.GetCustomAttributes<MatrixEventAttribute>()?
-                                .Any(y => y.EventName == event_type) ?? false) ?? typeof(object)
-                        )
-                });
-            }
-            return stateEvent;
-        }
-        set {
-            var stateEvent = InitialState.FirstOrDefault(x => x.Type == event_type && x.StateKey == event_key);
-            if (stateEvent == null)
-                InitialState.Add(value);
-            else
-                InitialState[InitialState.IndexOf(stateEvent)] = value;
-        }
-    }
-
-    public Dictionary<string, string> Validate() {
-        Dictionary<string, string> errors = new();
-        if (!Regex.IsMatch(RoomAliasName, @"[a-zA-Z0-9_\-]+$"))
-            errors.Add("room_alias_name",
-                "Room alias name must only contain letters, numbers, underscores, and hyphens.");
-
-        return errors;
-    }
-}
diff --git a/MatrixRoomUtils.Core/Responses/CreationContentBaseType.cs b/MatrixRoomUtils.Core/Responses/CreationContentBaseType.cs
deleted file mode 100644
index 743c552..0000000
--- a/MatrixRoomUtils.Core/Responses/CreationContentBaseType.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core.Responses;
-
-public class CreationContentBaseType {
-    private readonly CreateRoomRequest createRoomRequest;
-
-    public CreationContentBaseType(CreateRoomRequest createRoomRequest) => this.createRoomRequest = createRoomRequest;
-
-    [JsonPropertyName("type")]
-    public string Type {
-        get => (string)createRoomRequest.CreationContent["type"];
-        set {
-            if (value is "null" or "") createRoomRequest.CreationContent.Remove("type");
-            else createRoomRequest.CreationContent["type"] = value;
-        }
-    }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/LoginResponse.cs b/MatrixRoomUtils.Core/Responses/LoginResponse.cs
deleted file mode 100644
index 239ea03..0000000
--- a/MatrixRoomUtils.Core/Responses/LoginResponse.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core.Responses;
-
-public class LoginResponse {
-    [JsonPropertyName("access_token")]
-    public string AccessToken { get; set; }
-
-    [JsonPropertyName("device_id")]
-    public string DeviceId { get; set; }
-
-    [JsonPropertyName("home_server")]
-    public string Homeserver { get; set; }
-
-    [JsonPropertyName("user_id")]
-    public string UserId { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
deleted file mode 100644
index a7f9187..0000000
--- a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Text.Json.Nodes;
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.Responses;
-
-public class StateEventResponse : StateEvent {
-    [JsonPropertyName("origin_server_ts")]
-    public ulong OriginServerTs { get; set; }
-
-    [JsonPropertyName("room_id")]
-    public string RoomId { get; set; }
-
-    [JsonPropertyName("sender")]
-    public string Sender { get; set; }
-
-    [JsonPropertyName("unsigned")]
-    public UnsignedData? Unsigned { get; set; }
-
-    [JsonPropertyName("event_id")]
-    public string EventId { get; set; }
-
-    [JsonPropertyName("user_id")]
-    public string UserId { get; set; }
-
-    [JsonPropertyName("replaces_state")]
-    public string ReplacesState { get; set; }
-
-    public class UnsignedData {
-        [JsonPropertyName("age")]
-        public ulong? Age { get; set; }
-
-        [JsonPropertyName("redacted_because")]
-        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; }
-    }
-}
diff --git a/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs b/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs
deleted file mode 100644
index eced379..0000000
--- a/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-using System.Net.Http.Json;
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using System.Web;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Responses;
-using MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-namespace MatrixRoomUtils.Core.RoomTypes;
-
-public class GenericRoom {
-    internal readonly AuthenticatedHomeServer _homeServer;
-    internal readonly MatrixHttpClient _httpClient;
-
-    public GenericRoom(AuthenticatedHomeServer homeServer, string roomId) {
-        _homeServer = homeServer;
-        _httpClient = homeServer._httpClient;
-        RoomId = roomId;
-        if (GetType() != typeof(SpaceRoom))
-            AsSpace = new SpaceRoom(homeServer, RoomId);
-    }
-
-    public string RoomId { get; set; }
-
-    [Obsolete("", true)]
-    public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "") {
-        var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
-        if (!string.IsNullOrEmpty(type)) url += $"/{type}";
-        if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}";
-        return await _httpClient.GetFromJsonAsync<JsonElement>(url);
-    }
-
-    public async IAsyncEnumerable<StateEventResponse?> GetFullStateAsync() {
-        var res = await _httpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/state");
-        var result =
-            JsonSerializer.DeserializeAsyncEnumerable<StateEventResponse>(await res.Content.ReadAsStreamAsync());
-        await foreach (var resp in result) {
-            yield return resp;
-        }
-    }
-
-    public async Task<T?> GetStateAsync<T>(string type, string stateKey = "") {
-        var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
-        if (!string.IsNullOrEmpty(type)) url += $"/{type}";
-        if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}";
-        try {
-#if DEBUG && false
-            var resp = await _httpClient.GetFromJsonAsync<JsonObject>(url);
-            try {
-                _homeServer._httpClient.PostAsJsonAsync(
-                    "http://localhost:5116/validate/" + typeof(T).AssemblyQualifiedName, resp);
-            }
-            catch (Exception e) {
-                Console.WriteLine("[!!] Checking state response failed: " + e);
-            }
-
-            return resp.Deserialize<T>();
-#else
-            var resp = await _httpClient.GetFromJsonAsync<T>(url);
-            return resp;
-#endif
-        }
-        catch (MatrixException e) {
-            if (e is not { ErrorCode: "M_NOT_FOUND" }) {
-                throw;
-            }
-
-            Console.WriteLine(e);
-            return default;
-        }
-    }
-
-    public async Task<MessagesResponse> GetMessagesAsync(string from = "", int limit = 10, string dir = "b",
-        string filter = "") {
-        var url = $"/_matrix/client/v3/rooms/{RoomId}/messages?from={from}&limit={limit}&dir={dir}";
-        if (!string.IsNullOrEmpty(filter)) url += $"&filter={filter}";
-        var res = await _httpClient.GetFromJsonAsync<MessagesResponse>(url);
-        return res ?? new MessagesResponse();
-    }
-
-    public async Task<string> GetNameAsync() {
-        try {
-            var res = await GetStateAsync<RoomNameEventData>("m.room.name");
-            return res?.Name ?? RoomId;
-        }
-        catch (MatrixException e) {
-            return $"{RoomId} ({e.ErrorCode})";
-        }
-    }
-
-    public async Task JoinAsync(string[]? homeservers = null, string? reason = null) {
-        var join_url = $"/_matrix/client/v3/join/{HttpUtility.UrlEncode(RoomId)}";
-        Console.WriteLine($"Calling {join_url} with {homeservers?.Length ?? 0} via's...");
-        if (homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] };
-        var fullJoinUrl = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers);
-        var res = await _httpClient.PostAsJsonAsync(fullJoinUrl, new {
-            reason
-        });
-    }
-
-    public async IAsyncEnumerable<StateEventResponse> GetMembersAsync(bool joinedOnly = true) {
-        var res = GetFullStateAsync();
-        await foreach (var member in res) {
-            if (member.Type != "m.room.member") continue;
-            if (joinedOnly && (member.TypedContent as RoomMemberEventData).Membership is not "join") continue;
-            yield return member;
-        }
-    }
-
-    public async Task<List<string>> GetAliasesAsync() {
-        var res = await GetStateAsync<RoomAliasEventData>("m.room.aliases");
-        return res.Aliases;
-    }
-
-    public async Task<CanonicalAliasEventData?> GetCanonicalAliasAsync() =>
-        await GetStateAsync<CanonicalAliasEventData>("m.room.canonical_alias");
-
-    public async Task<RoomTopicEventData?> GetTopicAsync() =>
-        await GetStateAsync<RoomTopicEventData>("m.room.topic");
-
-    public async Task<RoomAvatarEventData?> GetAvatarUrlAsync() =>
-        await GetStateAsync<RoomAvatarEventData>("m.room.avatar");
-
-    public async Task<JoinRulesEventData> GetJoinRuleAsync() =>
-        await GetStateAsync<JoinRulesEventData>("m.room.join_rules");
-
-    public async Task<HistoryVisibilityEventData?> GetHistoryVisibilityAsync() =>
-        await GetStateAsync<HistoryVisibilityEventData>("m.room.history_visibility");
-
-    public async Task<GuestAccessEventData?> GetGuestAccessAsync() =>
-        await GetStateAsync<GuestAccessEventData>("m.room.guest_access");
-
-    public async Task<RoomCreateEventData> GetCreateEventAsync() =>
-        await GetStateAsync<RoomCreateEventData>("m.room.create");
-
-    public async Task<string?> GetRoomType() {
-        var res = await GetStateAsync<RoomCreateEventData>("m.room.create");
-        return res.Type;
-    }
-
-    public async Task ForgetAsync() =>
-        await _httpClient.PostAsync($"/_matrix/client/v3/rooms/{RoomId}/forget", null);
-
-    public async Task LeaveAsync(string? reason = null) =>
-        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/leave", new {
-            reason
-        });
-
-    public async Task KickAsync(string userId, string? reason = null) =>
-        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/kick",
-            new UserIdAndReason() { UserId = userId, Reason = reason });
-
-    public async Task BanAsync(string userId, string? reason = null) =>
-        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/ban",
-            new UserIdAndReason() { UserId = userId, Reason = reason });
-
-    public async Task UnbanAsync(string userId) =>
-        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/unban",
-            new UserIdAndReason() { UserId = userId });
-
-    public async Task<EventIdResponse> SendStateEventAsync(string eventType, object content) =>
-        await (await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType}", content))
-            .Content.ReadFromJsonAsync<EventIdResponse>();
-
-    public async Task<EventIdResponse> SendMessageEventAsync(string eventType, RoomMessageEventData content) {
-        var res = await _httpClient.PutAsJsonAsync(
-            $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(), content);
-        var resu = await res.Content.ReadFromJsonAsync<EventIdResponse>();
-        return resu;
-    }
-
-    public async Task<EventIdResponse> SendFileAsync(string eventType, string fileName, Stream fileStream) {
-        var content = new MultipartFormDataContent();
-        content.Add(new StreamContent(fileStream), "file", fileName);
-        var res = await
-            (
-                await _httpClient.PutAsync(
-                    $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(),
-                    content
-                )
-            )
-            .Content.ReadFromJsonAsync<EventIdResponse>();
-        return res;
-    }
-
-    public readonly SpaceRoom AsSpace;
-}
diff --git a/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs b/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
deleted file mode 100644
index 1b93064..0000000
--- a/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Text.Json;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
-
-namespace MatrixRoomUtils.Core.RoomTypes;
-
-public class SpaceRoom : GenericRoom {
-    private readonly AuthenticatedHomeServer _homeServer;
-    private readonly GenericRoom _room;
-
-    public SpaceRoom(AuthenticatedHomeServer homeServer, string roomId) : base(homeServer, roomId) {
-        _homeServer = homeServer;
-    }
-
-    private static SemaphoreSlim _semaphore = new(1, 1);
-    public async IAsyncEnumerable<GenericRoom> GetRoomsAsync(bool includeRemoved = false) {
-        await _semaphore.WaitAsync();
-        var rooms = new List<GenericRoom>();
-        var state = GetFullStateAsync();
-        await foreach (var stateEvent in state) {
-            if (stateEvent.Type != "m.space.child") continue;
-            if (stateEvent.RawContent.ToJson() != "{}" || includeRemoved)
-                yield return await _homeServer.GetRoom(stateEvent.StateKey);
-        }
-        _semaphore.Release();
-    }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs b/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs
deleted file mode 100644
index 4bc785a..0000000
--- a/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-using System.Net.Http.Headers;
-using System.Net.Http.Json;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Responses;
-using Microsoft.Extensions.Logging;
-
-namespace MatrixRoomUtils.Core.Services;
-
-public class HomeserverProviderService {
-    private readonly TieredStorageService _tieredStorageService;
-    private readonly ILogger<HomeserverProviderService> _logger;
-    private readonly HomeserverResolverService _homeserverResolverService;
-
-    public HomeserverProviderService(TieredStorageService tieredStorageService,
-        ILogger<HomeserverProviderService> logger, HomeserverResolverService homeserverResolverService) {
-        Console.WriteLine("Homeserver provider service instantiated!");
-        _tieredStorageService = tieredStorageService;
-        _logger = logger;
-        _homeserverResolverService = homeserverResolverService;
-        logger.LogDebug(
-            $"New HomeserverProviderService created with TieredStorageService<{string.Join(", ", tieredStorageService.GetType().GetProperties().Select(x => x.Name))}>!");
-    }
-
-    private static Dictionary<string, SemaphoreSlim> _authenticatedHomeserverSemaphore = new();
-    private static Dictionary<string, AuthenticatedHomeServer> _authenticatedHomeServerCache = new();
-
-    public async Task<AuthenticatedHomeServer> GetAuthenticatedWithToken(string homeserver, string accessToken,
-        string? overrideFullDomain = null) {
-        SemaphoreSlim sem = _authenticatedHomeserverSemaphore.GetOrCreate(homeserver+accessToken, _ => new SemaphoreSlim(1, 1));
-        await sem.WaitAsync();
-        if (_authenticatedHomeServerCache.ContainsKey(homeserver+accessToken)) {
-            sem.Release();
-            return _authenticatedHomeServerCache[homeserver+accessToken];
-        }
-
-        var hs = new AuthenticatedHomeServer(_tieredStorageService, homeserver, accessToken);
-        hs.FullHomeServerDomain = overrideFullDomain ??
-                                  await _homeserverResolverService.ResolveHomeserverFromWellKnown(homeserver);
-        hs._httpClient.Dispose();
-        hs._httpClient = new MatrixHttpClient { BaseAddress = new Uri(hs.FullHomeServerDomain) };
-        hs._httpClient.Timeout = TimeSpan.FromSeconds(120);
-        hs._httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
-
-        hs.WhoAmI = (await hs._httpClient.GetFromJsonAsync<WhoAmIResponse>("/_matrix/client/v3/account/whoami"))!;
-
-        _authenticatedHomeServerCache[homeserver+accessToken] = hs;
-        sem.Release();
-
-        return hs;
-    }
-
-    public async Task<RemoteHomeServer> GetRemoteHomeserver(string homeserver, string? overrideFullDomain = null) {
-        var hs = new RemoteHomeServer(homeserver);
-        hs.FullHomeServerDomain = overrideFullDomain ??
-                                  await _homeserverResolverService.ResolveHomeserverFromWellKnown(homeserver);
-        hs._httpClient.Dispose();
-        hs._httpClient = new MatrixHttpClient { BaseAddress = new Uri(hs.FullHomeServerDomain) };
-        hs._httpClient.Timeout = TimeSpan.FromSeconds(120);
-        return hs;
-    }
-
-    public async Task<LoginResponse> Login(string homeserver, string user, string password,
-        string? overrideFullDomain = null) {
-        var hs = await GetRemoteHomeserver(homeserver, overrideFullDomain);
-        var payload = new LoginRequest {
-            Identifier = new() { User = user },
-            Password = password
-        };
-        var resp = await hs._httpClient.PostAsJsonAsync("/_matrix/client/v3/login", payload);
-        var data = await resp.Content.ReadFromJsonAsync<LoginResponse>();
-        return data!;
-    }
-
-    private class LoginRequest {
-        [JsonPropertyName("type")]
-        public string Type { get; set; } = "m.login.password";
-
-        [JsonPropertyName("identifier")]
-        public LoginIdentifier Identifier { get; set; } = new();
-
-        [JsonPropertyName("password")]
-        public string Password { get; set; } = "";
-
-        [JsonPropertyName("initial_device_display_name")]
-        public string InitialDeviceDisplayName { get; set; } = "Rory&::LibMatrix";
-
-        public class LoginIdentifier {
-            [JsonPropertyName("type")]
-            public string Type { get; set; } = "m.id.user";
-
-            [JsonPropertyName("user")]
-            public string User { get; set; } = "";
-        }
-    }
-}
diff --git a/MatrixRoomUtils.Core/Services/HomeserverResolverService.cs b/MatrixRoomUtils.Core/Services/HomeserverResolverService.cs
deleted file mode 100644
index 5856000..0000000
--- a/MatrixRoomUtils.Core/Services/HomeserverResolverService.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using System.Net.Http.Json;
-using System.Text.Json;
-using MatrixRoomUtils.Core.Extensions;
-using Microsoft.Extensions.Logging;
-
-namespace MatrixRoomUtils.Core.Services;
-
-public class HomeserverResolverService {
-    private readonly MatrixHttpClient _httpClient = new();
-    private readonly ILogger<HomeserverResolverService> _logger;
-
-    private static readonly Dictionary<string, string> _wellKnownCache = new();
-    private static readonly Dictionary<string, SemaphoreSlim> _wellKnownSemaphores = new();
-
-    public HomeserverResolverService(ILogger<HomeserverResolverService> logger) {
-        _logger = logger;
-    }
-
-    public async Task<string> ResolveHomeserverFromWellKnown(string homeserver) {
-        var res = await _resolveHomeserverFromWellKnown(homeserver);
-        if (!res.StartsWith("http")) res = "https://" + res;
-        if (res.EndsWith(":443")) res = res.Substring(0, res.Length - 4);
-        return res;
-    }
-
-    private async Task<string> _resolveHomeserverFromWellKnown(string homeserver) {
-        if (homeserver is null) throw new ArgumentNullException(nameof(homeserver));
-        SemaphoreSlim sem = _wellKnownSemaphores.GetOrCreate(homeserver, _ => new SemaphoreSlim(1, 1));
-        await sem.WaitAsync();
-        if (_wellKnownCache.ContainsKey(homeserver)) {
-            sem.Release();
-            return _wellKnownCache[homeserver];
-        }
-
-        string? result = null;
-        _logger.LogInformation($"Attempting to resolve homeserver: {homeserver}");
-        result ??= await _tryResolveFromClientWellknown(homeserver);
-        result ??= await _tryResolveFromServerWellknown(homeserver);
-        result ??= await _tryCheckIfDomainHasHomeserver(homeserver);
-
-        if (result is not null) {
-            _logger.LogInformation($"Resolved homeserver: {homeserver} -> {result}");
-            _wellKnownCache[homeserver] = result;
-            sem.Release();
-            return result;
-        }
-
-        throw new InvalidDataException($"Failed to resolve homeserver for {homeserver}! Is it online and configured correctly?");
-    }
-
-    private async Task<string?> _tryResolveFromClientWellknown(string homeserver) {
-        if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver;
-        if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/client")) {
-            var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/client");
-            var hs = resp.GetProperty("m.homeserver").GetProperty("base_url").GetString();
-            return hs;
-        }
-
-        _logger.LogInformation("No client well-known...");
-        return null;
-    }
-
-    private async Task<string?> _tryResolveFromServerWellknown(string homeserver) {
-        if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver;
-        if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/server")) {
-            var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/server");
-            var hs = resp.GetProperty("m.server").GetString();
-            return hs;
-        }
-
-        _logger.LogInformation("No server well-known...");
-        return null;
-    }
-
-    private async Task<string?> _tryCheckIfDomainHasHomeserver(string homeserver) {
-        _logger.LogInformation($"Checking if {homeserver} hosts a homeserver...");
-        if (await _httpClient.CheckSuccessStatus($"{homeserver}/_matrix/client/versions"))
-            return homeserver;
-        _logger.LogInformation("No homeserver on shortname...");
-        return null;
-    }
-
-    private async Task<string?> _tryCheckIfSubDomainHasHomeserver(string homeserver, string subdomain) {
-        homeserver = homeserver.Replace("https://", $"https://{subdomain}.");
-        return await _tryCheckIfDomainHasHomeserver(homeserver);
-    }
-}
diff --git a/MatrixRoomUtils.Core/Services/ServiceInstaller.cs b/MatrixRoomUtils.Core/Services/ServiceInstaller.cs
deleted file mode 100644
index bd5b1bd..0000000
--- a/MatrixRoomUtils.Core/Services/ServiceInstaller.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using MatrixRoomUtils.Core.Extensions;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace MatrixRoomUtils.Core.Services;
-
-public static class ServiceInstaller {
-
-    public static IServiceCollection AddRoryLibMatrixServices(this IServiceCollection services, RoryLibMatrixConfiguration? config = null) {
-        //Check required services
-        if (!services.Any(x => x.ServiceType == typeof(TieredStorageService)))
-            throw new Exception("[MRUCore/DI] No TieredStorageService has been registered!");
-        //Add config
-        if(config is not null)
-            services.AddSingleton(config);
-        else {
-            services.AddSingleton(new RoryLibMatrixConfiguration());
-        }
-        //Add services
-        services.AddSingleton<HomeserverProviderService>();
-        services.AddSingleton<HomeserverResolverService>();
-        // services.AddScoped<MatrixHttpClient>();
-        return services;
-    }
-
-
-}
-
-public class RoryLibMatrixConfiguration {
-    public string AppName { get; set; } = "Rory&::LibMatrix";
-}
diff --git a/MatrixRoomUtils.Core/Services/TieredStorageService.cs b/MatrixRoomUtils.Core/Services/TieredStorageService.cs
deleted file mode 100644
index 2f27443..0000000
--- a/MatrixRoomUtils.Core/Services/TieredStorageService.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using MatrixRoomUtils.Core.Interfaces.Services;
-
-namespace MatrixRoomUtils.Core.Services; 
-
-public class TieredStorageService {
-    public IStorageProvider CacheStorageProvider { get; }
-    public IStorageProvider DataStorageProvider { get; }
-
-    public TieredStorageService(IStorageProvider cacheStorageProvider, IStorageProvider dataStorageProvider) {
-        CacheStorageProvider = cacheStorageProvider;
-        DataStorageProvider = dataStorageProvider;
-    }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEvent.cs b/MatrixRoomUtils.Core/StateEvent.cs
deleted file mode 100644
index 785c637..0000000
--- a/MatrixRoomUtils.Core/StateEvent.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-using System.Diagnostics;
-using System.Reflection;
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
-using MatrixRoomUtils.Core.StateEventTypes;
-
-namespace MatrixRoomUtils.Core;
-
-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 {
-                return RawContent.Deserialize(GetType)!;
-            }
-            catch (JsonException e) {
-                Console.WriteLine(e);
-                Console.WriteLine("Content:\n" + ObjectExtensions.ToJson(RawContent));
-            }
-
-            return null;
-        }
-        set => RawContent = JsonSerializer.Deserialize<JsonObject>(JsonSerializer.Serialize(value));
-    }
-
-    [JsonPropertyName("state_key")]
-    public string StateKey { get; set; } = "";
-
-    private string _type;
-
-    [JsonPropertyName("type")]
-    public string Type {
-        get => _type;
-        set {
-            _type = value;
-            // if (RawContent is not null && this is StateEventResponse stateEventResponse) {
-            //     if (File.Exists($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json")) return;
-            //     var x = GetType.Name;
-            // }
-        }
-    }
-
-    [JsonPropertyName("replaces_state")]
-    public string? ReplacesState { get; set; }
-
-    private JsonObject? _rawContent;
-
-    [JsonPropertyName("content")]
-    public JsonObject? RawContent {
-        get => _rawContent;
-        set {
-            _rawContent = value;
-            // if (Type is not null && this is StateEventResponse stateEventResponse) {
-            //     if (File.Exists($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json")) return;
-            //     var x = GetType.Name;
-            // }
-        }
-    }
-
-    [JsonIgnore]
-    public Type GetType {
-        get {
-            var type = GetStateEventType(Type);
-
-            //special handling for some types
-            // if (type == typeof(RoomEmotesEventData)) {
-            //     RawContent["emote"] = RawContent["emote"]?.AsObject() ?? new JsonObject();
-            // }
-            //
-            // if (this is StateEventResponse stateEventResponse) {
-            //     if (type == null || type == typeof(object)) {
-            //         Console.WriteLine($"Warning: unknown event type '{Type}'!");
-            //         Console.WriteLine(RawContent.ToJson());
-            //         Directory.CreateDirectory($"unknown_state_events/{Type}");
-            //         File.WriteAllText($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json",
-            //             RawContent.ToJson());
-            //         Console.WriteLine($"Saved to unknown_state_events/{Type}/{stateEventResponse.EventId}.json");
-            //     }
-            //     else if (RawContent is not null && RawContent.FindExtraJsonObjectFields(type)) {
-            //         Directory.CreateDirectory($"unknown_state_events/{Type}");
-            //         File.WriteAllText($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json",
-            //             RawContent.ToJson());
-            //         Console.WriteLine($"Saved to unknown_state_events/{Type}/{stateEventResponse.EventId}.json");
-            //     }
-            // }
-
-            return type;
-        }
-    }
-
-    //debug
-    public string dtype {
-        get {
-            var res = GetType().Name switch {
-                "StateEvent`1" => $"StateEvent",
-                _ => GetType().Name
-            };
-            return res;
-        }
-    }
-
-    public string cdtype => TypedContent.GetType().Name;
-}
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Common/MjolnirShortcodeEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Common/MjolnirShortcodeEventData.cs
deleted file mode 100644
index 66dcdb9..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Common/MjolnirShortcodeEventData.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Common;
-
-[MatrixEvent(EventName = "org.matrix.mjolnir.shortcode")]
-public class MjolnirShortcodeEventData : IStateEventType {
-    [JsonPropertyName("shortcode")]
-    public string? Shortcode { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs
deleted file mode 100644
index c263a3a..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Common/RoomEmotesEventData.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-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 {
-
-    }
-}
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/CanonicalAliasEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/CanonicalAliasEventData.cs
deleted file mode 100644
index 354f99d..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/CanonicalAliasEventData.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.room.canonical_alias")]
-public class CanonicalAliasEventData : IStateEventType {
-    [JsonPropertyName("alias")]
-    public string? Alias { get; set; }
-    [JsonPropertyName("alt_aliases")]
-    public string[]? AltAliases { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/GuestAccessEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/GuestAccessEventData.cs
deleted file mode 100644
index c5b92ad..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/GuestAccessEventData.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.guest_access")]
-public class GuestAccessEventData : IStateEventType {
-    [JsonPropertyName("guest_access")]
-    public string GuestAccess { get; set; }
-
-    public bool IsGuestAccessEnabled {
-        get => GuestAccess == "can_join";
-        set => GuestAccess = value ? "can_join" : "forbidden";
-    }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/HistoryVisibilityEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/HistoryVisibilityEventData.cs
deleted file mode 100644
index e0785b9..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/HistoryVisibilityEventData.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.history_visibility")]
-public class HistoryVisibilityEventData : IStateEventType {
-    [JsonPropertyName("history_visibility")]
-    public string HistoryVisibility { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/JoinRulesEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/JoinRulesEventData.cs
deleted file mode 100644
index f5410dc..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/JoinRulesEventData.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.join_rules")]
-public class JoinRulesEventData : IStateEventType {
-    private static string Public = "public";
-    private static string Invite = "invite";
-    private static string Knock = "knock";
-
-    [JsonPropertyName("join_rule")]
-    public string JoinRule { get; set; }
-
-    [JsonPropertyName("allow")]
-    public List<string> Allow { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/PolicyRuleStateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/PolicyRuleStateEventData.cs
deleted file mode 100644
index ef94cff..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/PolicyRuleStateEventData.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.policy.rule.user")]
-[MatrixEvent(EventName = "m.policy.rule.server")]
-[MatrixEvent(EventName = "org.matrix.mjolnir.rule.server")]
-public class PolicyRuleStateEventData : IStateEventType {
-    /// <summary>
-    ///     Entity this ban applies to, can use * and ? as globs.
-    /// </summary>
-    [JsonPropertyName("entity")]
-    public string Entity { get; set; }
-
-    /// <summary>
-    ///     Reason this user is banned
-    /// </summary>
-    [JsonPropertyName("reason")]
-    public string? Reason { get; set; }
-
-    /// <summary>
-    ///     Suggested action to take
-    /// </summary>
-    [JsonPropertyName("recommendation")]
-    public string? Recommendation { get; set; }
-
-    /// <summary>
-    ///     Expiry time in milliseconds since the unix epoch, or null if the ban has no expiry.
-    /// </summary>
-    [JsonPropertyName("support.feline.policy.expiry.rev.2")] //stable prefix: expiry, msc pending
-    public long? Expiry { get; set; }
-
-    //utils
-    /// <summary>
-    ///     Readable expiry time, provided for easy interaction
-    /// </summary>
-    [JsonPropertyName("gay.rory.matrix_room_utils.readable_expiry_time_utc")]
-    public DateTime? ExpiryDateTime {
-        get => Expiry == null ? null : DateTimeOffset.FromUnixTimeMilliseconds(Expiry.Value).DateTime;
-        set => Expiry = ((DateTimeOffset)value).ToUnixTimeMilliseconds();
-    }
-}
-
-public static class PolicyRecommendationTypes {
-    /// <summary>
-    ///     Ban this user
-    /// </summary>
-    public static string Ban = "m.ban";
-
-    /// <summary>
-    ///     Mute this user
-    /// </summary>
-    public static string Mute = "support.feline.policy.recommendation_mute"; //stable prefix: m.mute, msc pending
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/PresenceStateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/PresenceStateEventData.cs
deleted file mode 100644
index c5eb2ea..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/PresenceStateEventData.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.presence")]
-public class PresenceStateEventData : IStateEventType {
-    [JsonPropertyName("presence")]
-    public string Presence { get; set; }
-    [JsonPropertyName("last_active_ago")]
-    public long LastActiveAgo { get; set; }
-    [JsonPropertyName("currently_active")]
-    public bool CurrentlyActive { get; set; }
-    [JsonPropertyName("status_msg")]
-    public string StatusMessage { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/ProfileResponseEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/ProfileResponseEventData.cs
deleted file mode 100644
index f3a0ce9..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/ProfileResponseEventData.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-public class ProfileResponseEventData : IStateEventType {
-    [JsonPropertyName("avatar_url")]
-    public string? AvatarUrl { get; set; } = "";
-
-    [JsonPropertyName("displayname")]
-    public string? DisplayName { get; set; } = "";
-}
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAliasEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAliasEventData.cs
deleted file mode 100644
index 611e8a2..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAliasEventData.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.alias")]
-public class RoomAliasEventData : IStateEventType {
-    [JsonPropertyName("aliases")]
-    public List<string>? Aliases { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs
deleted file mode 100644
index a14e4c5..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomAvatarEventData.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-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; }
-    }
-}
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs
deleted file mode 100644
index 6127028..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomCreateEventData.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.create")]
-public class RoomCreateEventData : IStateEventType {
-    [JsonPropertyName("room_version")]
-    public string? RoomVersion { get; set; }
-    [JsonPropertyName("creator")]
-    public string? Creator { get; set; }
-    [JsonPropertyName("m.federate")]
-    public bool? Federate { get; set; }
-    [JsonPropertyName("predecessor")]
-    public RoomCreatePredecessor? Predecessor { get; set; }
-    [JsonPropertyName("type")]
-    public string? Type { get; set; }
-
-    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/RoomEncryptionEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomEncryptionEventData.cs
deleted file mode 100644
index c473082..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomEncryptionEventData.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.room.encryption")]
-public class RoomEncryptionEventData : IStateEventType {
-    [JsonPropertyName("algorithm")]
-    public string? Algorithm { get; set; }
-    [JsonPropertyName("rotation_period_ms")]
-    public ulong? RotationPeriodMs { get; set; }
-    [JsonPropertyName("rotation_period_msgs")]
-    public ulong? RotationPeriodMsgs { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMemberEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMemberEventData.cs
deleted file mode 100644
index a543a2f..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMemberEventData.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.member")]
-public class RoomMemberEventData : IStateEventType {
-    [JsonPropertyName("reason")]
-    public string? Reason { get; set; }
-
-    [JsonPropertyName("membership")]
-    public string Membership { get; set; } = null!;
-
-    [JsonPropertyName("displayname")]
-    public string? Displayname { get; set; }
-
-    [JsonPropertyName("is_direct")]
-    public bool? IsDirect { get; set; }
-
-    [JsonPropertyName("avatar_url")]
-    public string? AvatarUrl { get; set; }
-
-    [JsonPropertyName("kind")]
-    public string? Kind { get; set; }
-    
-    [JsonPropertyName("join_authorised_via_users_server")]
-    public string? JoinAuthorisedViaUsersServer { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMessageEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMessageEventData.cs
deleted file mode 100644
index 2c56b88..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomMessageEventData.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.room.message")]
-public class RoomMessageEventData : IStateEventType {
-    [JsonPropertyName("body")]
-    public string Body { get; set; }
-    [JsonPropertyName("msgtype")]
-    public string MessageType { get; set; } = "m.notice";
-
-    [JsonPropertyName("formatted_body")]
-    public string FormattedBody { get; set; }
-
-    [JsonPropertyName("format")]
-    public string Format { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomNameEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomNameEventData.cs
deleted file mode 100644
index e5b7d59..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomNameEventData.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.room.name")]
-public class RoomNameEventData : IStateEventType {
-    [JsonPropertyName("name")]
-    public string? Name { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPinnedEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPinnedEventData.cs
deleted file mode 100644
index d84e962..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPinnedEventData.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.room.pinned_events")]
-public class RoomPinnedEventData : IStateEventType {
-    [JsonPropertyName("pinned")]
-    public string[]? PinnedEvents { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs
deleted file mode 100644
index 1cde660..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomPowerLevelEventData.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.power_levels")]
-public class RoomPowerLevelEventData : IStateEventType {
-    [JsonPropertyName("ban")]
-    public int Ban { get; set; } // = 50;
-
-    [JsonPropertyName("events_default")]
-    public int EventsDefault { get; set; } // = 0;
-
-    [JsonPropertyName("events")]
-    public Dictionary<string, int> Events { get; set; } // = null!;
-
-    [JsonPropertyName("invite")]
-    public int Invite { get; set; } // = 50;
-
-    [JsonPropertyName("kick")]
-    public int Kick { get; set; } // = 50;
-
-    [JsonPropertyName("notifications")]
-    public NotificationsPL NotificationsPl { get; set; } // = null!;
-
-    [JsonPropertyName("redact")]
-    public int Redact { get; set; } // = 50;
-
-    [JsonPropertyName("state_default")]
-    public int StateDefault { get; set; } // = 50;
-
-    [JsonPropertyName("users")]
-    public Dictionary<string, int> Users { get; set; } // = null!;
-
-    [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;
-    }
-
-    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);
-    }
-}
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTopicEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTopicEventData.cs
deleted file mode 100644
index cdd62a1..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTopicEventData.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.room.topic")]
-[MatrixEvent(EventName = "org.matrix.msc3765.topic", Legacy = true)]
-public class RoomTopicEventData : IStateEventType {
-    [JsonPropertyName("topic")]
-    public string? Topic { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTypingEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTypingEventData.cs
deleted file mode 100644
index 017a117..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/RoomTypingEventData.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.typing")]
-public class RoomTypingEventData : IStateEventType {
-    [JsonPropertyName("user_ids")]
-    public string[]? UserIds { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/ServerACLEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/ServerACLEventData.cs
deleted file mode 100644
index 4b559c6..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/ServerACLEventData.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.room.server_acl")]
-public class ServerACLEventData : IStateEventType {
-    [JsonPropertyName("allow")]
-    public List<string> Allow { get; set; } // = null!;
-
-    [JsonPropertyName("deny")]
-    public List<string> Deny { get; set; } // = null!;
-
-    [JsonPropertyName("allow_ip_literals")]
-    public bool AllowIpLiterals { get; set; } // = false;
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceChildEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceChildEventData.cs
deleted file mode 100644
index bb62d92..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceChildEventData.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec; 
-
-[MatrixEvent(EventName = "m.space.child")]
-public class SpaceChildEventData : IStateEventType {
-    [JsonPropertyName("auto_join")]
-    public bool? AutoJoin { get; set; }
-    [JsonPropertyName("via")]
-    public string[]? Via { get; set; }
-    [JsonPropertyName("suggested")]
-    public bool? Suggested { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceParentEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceParentEventData.cs
deleted file mode 100644
index a40f7ae..0000000
--- a/MatrixRoomUtils.Core/StateEventTypes/Spec/SpaceParentEventData.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Text.Json.Serialization;
-using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Interfaces;
-
-namespace MatrixRoomUtils.Core.StateEventTypes.Spec;
-
-[MatrixEvent(EventName = "m.space.parent")]
-public class SpaceParentEventData : IStateEventType {
-    [JsonPropertyName("via")]
-    public string[]? Via { get; set; }
-
-    [JsonPropertyName("canonical")]
-    public bool? Canonical { get; set; }
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/UserIdAndReason.cs b/MatrixRoomUtils.Core/UserIdAndReason.cs
deleted file mode 100644
index 3801077..0000000
--- a/MatrixRoomUtils.Core/UserIdAndReason.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace MatrixRoomUtils.Core;
-
-internal class UserIdAndReason {
-    [JsonPropertyName("user_id")]
-    public string UserId { get; set; }
-    [JsonPropertyName("reason")]
-    public string? Reason { get; set; }
-}
\ No newline at end of file