diff --git a/.gitignore b/.gitignore
index 47d212e..33be3d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ MatrixRoomUtils.Web/wwwroot/MRU.tar.xz
*.tar.xz
matrix-sync.json
/patches/
+MatrixRoomUtils.Bot/bot_data/
+appsettings.Local.json
diff --git a/.idea/.idea.MatrixRoomUtils/.idea/indexLayout.xml b/.idea/.idea.MatrixRoomUtils/.idea/indexLayout.xml
index 7b08163..9c54b37 100644
--- a/.idea/.idea.MatrixRoomUtils/.idea/indexLayout.xml
+++ b/.idea/.idea.MatrixRoomUtils/.idea/indexLayout.xml
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
- <attachedFolders />
+ <attachedFolders>
+ <Path>MatrixRoomUtils.Bot/bot_data</Path>
+ </attachedFolders>
<explicitIncludes />
<explicitExcludes />
</component>
diff --git a/MatrixRoomUtils.Bot/MRUBot.cs b/MatrixRoomUtils.Bot/MRUBot.cs
index 9b2a395..157673d 100644
--- a/MatrixRoomUtils.Bot/MRUBot.cs
+++ b/MatrixRoomUtils.Bot/MRUBot.cs
@@ -1,55 +1,82 @@
-using System.CodeDom.Compiler;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using MatrixRoomUtils.Bot;
using MatrixRoomUtils.Core;
using MatrixRoomUtils.Core.Extensions;
using MatrixRoomUtils.Core.Helpers;
-using MatrixRoomUtils.Core.Responses;
using MatrixRoomUtils.Core.Services;
+using MatrixRoomUtils.Core.StateEventTypes;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class MRUBot : IHostedService {
private readonly HomeserverProviderService _homeserverProviderService;
private readonly ILogger<MRUBot> _logger;
+ private readonly MRUBotConfiguration _configuration;
- public MRUBot(HomeserverProviderService homeserverProviderService, ILogger<MRUBot> logger) {
+ public MRUBot(HomeserverProviderService homeserverProviderService, ILogger<MRUBot> logger,
+ MRUBotConfiguration configuration) {
Console.WriteLine("MRUBot hosted service instantiated!");
_homeserverProviderService = homeserverProviderService;
_logger = logger;
+ _configuration = configuration;
}
/// <summary>Triggered when the application host is ready to start the service.</summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
[SuppressMessage("ReSharper", "FunctionNeverReturns")]
public async Task StartAsync(CancellationToken cancellationToken) {
- var hs = await _homeserverProviderService.GetAuthenticatedWithToken("rory.gay", "syt_bXJ1Y29yZXRlc3Q_XKUmPswDGZBiLAmFfAut_1iO0KD");
+ Directory.GetFiles("bot_data/cache").ToList().ForEach(File.Delete);
+ AuthenticatedHomeServer hs;
+ try {
+ hs = await _homeserverProviderService.GetAuthenticatedWithToken(_configuration.Homeserver,
+ _configuration.AccessToken);
+ }
+ catch (Exception e) {
+ _logger.LogError(e.Message);
+ throw;
+ }
+
await (await hs.GetRoom("!DoHEdFablOLjddKWIp:rory.gay")).JoinAsync();
- // #pragma warning disable CS4014
- // Task.Run(async Task? () => {
- // #pragma warning restore CS4014
- // while (true) {
- // var rooms = await hs.GetJoinedRooms();
- // foreach (var room in rooms) {
- // var states = await room.GetStateAsync<List<StateEventResponse>>("");
- // foreach (var state in states) {
- // // Console.WriteLine(
- // // $"{state.RoomId}: {state.Type}::{state.StateKey} = {ObjectExtensions.ToJson(state.Content, indent: false)}");
- // }
- // }
- //
- // await Task.Delay(1000, cancellationToken);
- // }
- // }, cancellationToken);
- #pragma warning disable CS4014
- Task.Run(async Task? () => {
- #pragma warning restore CS4014
- SyncResult? sync = null;
- while (true) {
- sync = await hs.SyncHelper.Sync(sync?.NextBatch);
- _logger.LogInformation($"Got sync, next batch: {sync?.NextBatch}!");
- }
- }, cancellationToken);
-
+
+ hs.SyncHelper.InviteReceived += async (_, args) => {
+ // Console.WriteLine($"Got invite to {args.Key}:");
+ // foreach (var stateEvent in args.Value.InviteState.Events) {
+ // Console.WriteLine($"[{stateEvent.Sender}: {stateEvent.StateKey}::{stateEvent.Type}] " +
+ // ObjectExtensions.ToJson(stateEvent.Content, indent: false, ignoreNull: true));
+ // }
+
+ var inviteEvent =
+ args.Value.InviteState.Events.FirstOrDefault(x =>
+ x.Type == "m.room.member" && x.StateKey == hs.WhoAmI.UserId);
+ Console.WriteLine(
+ $"Got invite to {args.Key} by {inviteEvent.Sender} with reason: {(inviteEvent.TypedContent as MemberEventData).Reason}");
+ if (inviteEvent.Sender == "@emma:rory.gay") {
+ try {
+ await (await hs.GetRoom(args.Key)).JoinAsync(reason: "I was invited by Emma (Rory&)!");
+ }
+ catch (Exception e) {
+ Console.WriteLine(e);
+ await (await hs.GetRoom(args.Key)).LeaveAsync(reason: "I was unable to join the room: " + e);
+ }
+ }
+ };
+ hs.SyncHelper.TimelineEventReceived += async (_, @event) => {
+ Console.WriteLine(
+ $"Got timeline event in {@event.RoomId}: {@event.ToJson(indent: false, ignoreNull: true)}");
+
+ // Console.WriteLine(eventResponse.ToJson(indent: false));
+ if (@event is { Type: "m.room.message", TypedContent: MessageEventData message }) {
+ if (message is { MessageType: "m.text", Body: "!ping" }) {
+ Console.WriteLine(
+ $"Got ping from {@event.Sender} in {@event.RoomId} with message id {@event.EventId}!");
+ await (await hs.GetRoom(@event.RoomId)).SendMessageEventAsync("m.room.message",
+ new MessageEventData() { MessageType = "m.text", Body = "pong!" });
+ }
+ }
+ };
+
+ await hs.SyncHelper.RunSyncLoop(cancellationToken);
}
/// <summary>Triggered when the application host is performing a graceful shutdown.</summary>
diff --git a/MatrixRoomUtils.Bot/MRUBotConfiguration.cs b/MatrixRoomUtils.Bot/MRUBotConfiguration.cs
new file mode 100644
index 0000000..14d9b60
--- /dev/null
+++ b/MatrixRoomUtils.Bot/MRUBotConfiguration.cs
@@ -0,0 +1,11 @@
+using Microsoft.Extensions.Configuration;
+
+namespace MatrixRoomUtils.Bot;
+
+public class MRUBotConfiguration {
+ public MRUBotConfiguration(IConfiguration config) {
+ config.GetRequiredSection("Bot").Bind(this);
+ }
+ public string Homeserver { get; set; } = "";
+ public string AccessToken { get; set; } = "";
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Bot/MatrixRoomUtils.Bot.csproj b/MatrixRoomUtils.Bot/MatrixRoomUtils.Bot.csproj
index 095d0f6..a82b6aa 100644
--- a/MatrixRoomUtils.Bot/MatrixRoomUtils.Bot.csproj
+++ b/MatrixRoomUtils.Bot/MatrixRoomUtils.Bot.csproj
@@ -23,5 +23,9 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0-preview.5.23280.8" />
</ItemGroup>
-
+ <ItemGroup>
+ <Content Include="appsettings*.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
</Project>
diff --git a/MatrixRoomUtils.Bot/Program.cs b/MatrixRoomUtils.Bot/Program.cs
index 441003e..e8a5b96 100644
--- a/MatrixRoomUtils.Bot/Program.cs
+++ b/MatrixRoomUtils.Bot/Program.cs
@@ -7,20 +7,16 @@ using Microsoft.Extensions.Hosting;
Console.WriteLine("Hello, World!");
-using IHost host = Host.CreateDefaultBuilder(args)
- .ConfigureServices((_, services) => {
- services.AddScoped<TieredStorageService>(x =>
- new(
- cacheStorageProvider: new FileStorageProvider("data/cache/"),
- dataStorageProvider: new FileStorageProvider("data/data/")
- )
- );
-
- services.AddRoryLibMatrixServices();
-
- services.AddHostedService<MRUBot>();
- })
- .Build();
-
+var host = Host.CreateDefaultBuilder(args).ConfigureServices((_, services) => {
+ services.AddScoped<TieredStorageService>(x =>
+ new(
+ cacheStorageProvider: new FileStorageProvider("bot_data/cache/"),
+ dataStorageProvider: new FileStorageProvider("bot_data/data/")
+ )
+ );
+ services.AddScoped<MRUBotConfiguration>();
+ services.AddRoryLibMatrixServices();
+ services.AddHostedService<MRUBot>();
+}).UseConsoleLifetime().Build();
await host.RunAsync();
\ No newline at end of file
diff --git a/MatrixRoomUtils.Bot/Properties/launchSettings.json b/MatrixRoomUtils.Bot/Properties/launchSettings.json
new file mode 100644
index 0000000..997e294
--- /dev/null
+++ b/MatrixRoomUtils.Bot/Properties/launchSettings.json
@@ -0,0 +1,26 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "Default": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+
+ }
+ },
+ "Development": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+ "DOTNET_ENVIRONMENT": "Development"
+ }
+ },
+ "Local config": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+ "DOTNET_ENVIRONMENT": "Local"
+ }
+ }
+ }
+}
diff --git a/MatrixRoomUtils.Bot/appsettings.Development.json b/MatrixRoomUtils.Bot/appsettings.Development.json
new file mode 100644
index 0000000..27bbd50
--- /dev/null
+++ b/MatrixRoomUtils.Bot/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Bot/appsettings.json b/MatrixRoomUtils.Bot/appsettings.json
new file mode 100644
index 0000000..5668b53
--- /dev/null
+++ b/MatrixRoomUtils.Bot/appsettings.json
@@ -0,0 +1,13 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ },
+ "Bot": {
+ "Homeserver": "rory.gay",
+ "AccessToken": "syt_xxxxxxxxxxxxxxxxx"
+ }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
index 74e85b1..23e98ae 100644
--- a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
+++ b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
@@ -2,6 +2,7 @@ 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;
@@ -17,15 +18,16 @@ public class AuthenticatedHomeServer : IHomeServer {
public readonly HomeserverAdminApi Admin;
public readonly SyncHelper SyncHelper;
- public AuthenticatedHomeServer(string canonicalHomeServerDomain, string accessToken, TieredStorageService storage) {
+ public AuthenticatedHomeServer(TieredStorageService storage, string canonicalHomeServerDomain, string accessToken) {
_storage = storage;
- AccessToken = accessToken;
- HomeServerDomain = canonicalHomeServerDomain;
+ 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 { get; }
public string AccessToken { get; set; }
@@ -35,6 +37,7 @@ public class AuthenticatedHomeServer : IHomeServer {
_httpClient = new MatrixHttpClient { BaseAddress = new Uri(FullHomeServerDomain) };
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
Console.WriteLine("[AHS] Finished setting up http client");
+ WhoAmI = (await _httpClient.GetFromJsonAsync<WhoAmIResponse>("/_matrix/client/v3/account/whoami"))!;
return this;
}
@@ -54,7 +57,7 @@ public class AuthenticatedHomeServer : IHomeServer {
}
public async Task<string> UploadFile(string fileName, Stream fileStream, string contentType = "application/octet-stream") {
- var res = await _httpClient.PostAsync($"/_matrix/media/r0/upload?filename={fileName}", new StreamContent(fileStream));
+ 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()}");
@@ -65,7 +68,7 @@ public class AuthenticatedHomeServer : IHomeServer {
}
public async Task<Room> CreateRoom(CreateRoomRequest creationEvent) {
- var res = await _httpClient.PostAsJsonAsync("/_matrix/client/r0/createRoom", 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()}");
@@ -168,4 +171,14 @@ public class AuthenticatedHomeServer : IHomeServer {
} 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/Authentication/MatrixAuth.cs b/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
index 0f9eb58..83b279a 100644
--- a/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
+++ b/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
@@ -2,6 +2,7 @@ using System.Net.Http.Json;
using System.Text.Json;
using MatrixRoomUtils.Core.Extensions;
using MatrixRoomUtils.Core.Responses;
+using MatrixRoomUtils.Core.StateEventTypes;
namespace MatrixRoomUtils.Core.Authentication;
@@ -20,7 +21,7 @@ public class MatrixAuth {
initial_device_display_name = "Rory&::MatrixRoomUtils"
};
Console.WriteLine($"Sending login request to {homeserver}...");
- var resp = await hc.PostAsJsonAsync($"{homeserver}/_matrix/client/r0/login", payload);
+ var resp = await hc.PostAsJsonAsync($"{homeserver}/_matrix/client/v3/login", payload);
Console.WriteLine($"Login: {resp.StatusCode}");
var data = await resp.Content.ReadFromJsonAsync<JsonElement>();
if (!resp.IsSuccessStatusCode) Console.WriteLine("Login: " + data);
diff --git a/MatrixRoomUtils.Core/CreateEvent.cs b/MatrixRoomUtils.Core/CreateEvent.cs
new file mode 100644
index 0000000..a7022c5
--- /dev/null
+++ b/MatrixRoomUtils.Core/CreateEvent.cs
@@ -0,0 +1,20 @@
+using System.Text.Json.Serialization;
+
+namespace MatrixRoomUtils.Core;
+
+public class CreateEvent {
+ [JsonPropertyName("creator")]
+ public string Creator { get; set; }
+
+ [JsonPropertyName("room_version")]
+ public string RoomVersion { get; set; }
+
+ [JsonPropertyName("type")]
+ public string? Type { get; set; }
+
+ [JsonPropertyName("predecessor")]
+ public object? Predecessor { get; set; }
+
+ [JsonPropertyName("m.federate")]
+ public bool Federate { get; set; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/EventIdResponse.cs b/MatrixRoomUtils.Core/EventIdResponse.cs
new file mode 100644
index 0000000..77dc7f8
--- /dev/null
+++ b/MatrixRoomUtils.Core/EventIdResponse.cs
@@ -0,0 +1,8 @@
+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
new file mode 100644
index 0000000..9d3d3c0
--- /dev/null
+++ b/MatrixRoomUtils.Core/Extensions/ClassCollector.cs
@@ -0,0 +1,30 @@
+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();
+ // {
+ // List<Type> ret = new();
+ // foreach (var x in assembly.GetTypes().Where(x => x is { IsClass: true, IsAbstract: false } && x.GetInterfaces().Contains(typeof(T))).ToList()) {
+ // // Console.WriteLine($"[!!] Found class {x.FullName}");
+ // ret.Add(x);
+ // }
+ // return ret;
+ // }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs b/MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs
new file mode 100644
index 0000000..98b0aab
--- /dev/null
+++ b/MatrixRoomUtils.Core/Extensions/IEnumerableExtensions.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Text.Json;
+using MatrixRoomUtils.Core.Interfaces;
+using MatrixRoomUtils.Core.Responses;
+
+namespace MatrixRoomUtils.Core.Extensions;
+
+public static class IEnumerableExtensions {
+ public static List<StateEventResponse> DeserializeMatrixTypes(this List<JsonElement> stateEvents) {
+ return stateEvents.Select(DeserializeMatrixType).ToList();
+ }
+
+ public static StateEventResponse DeserializeMatrixType(this JsonElement stateEvent) {
+ var type = stateEvent.GetProperty("type").GetString();
+ var knownType = StateEvent.KnownStateEventTypes.FirstOrDefault(x => x.GetCustomAttribute<MatrixEventAttribute>()?.EventName == type);
+ if (knownType == null) {
+ Console.WriteLine($"Warning: unknown event type '{type}'!");
+ return new StateEventResponse();
+ }
+
+ var eventInstance = Activator.CreateInstance(typeof(StateEventResponse).MakeGenericType(knownType))!;
+ stateEvent.Deserialize(eventInstance.GetType());
+
+ return (StateEventResponse) eventInstance;
+ }
+
+ public static void Replace(this List<StateEvent> stateEvents, StateEvent old, StateEvent @new) {
+ var index = stateEvents.IndexOf(old);
+ if (index == -1) return;
+ stateEvents[index] = @new;
+ }
+}
+
+public class MatrixEventAttribute : Attribute {
+ public string EventName { get; set; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
index b007136..78f4456 100644
--- a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
@@ -1,12 +1,13 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json;
+using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace MatrixRoomUtils.Core.Extensions;
public static class JsonElementExtensions {
- public static void FindExtraJsonFields([DisallowNull] this JsonElement? res, Type t) {
+ public static void FindExtraJsonElementFields([DisallowNull] this JsonElement? res, Type t) {
var props = t.GetProperties();
var unknownPropertyFound = false;
foreach (var field in res.Value.EnumerateObject()) {
@@ -17,4 +18,18 @@ public static class JsonElementExtensions {
if (unknownPropertyFound) Console.WriteLine(res.Value.ToJson());
}
+ public static void FindExtraJsonObjectFields([DisallowNull] this JsonObject? res, Type t) {
+ var props = t.GetProperties();
+ var unknownPropertyFound = false;
+ foreach (var field in res) {
+ if (props.Any(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name == field.Key)) continue;
+ Console.WriteLine($"[!!] Unknown property {field.Key} in {t.Name}!");
+ unknownPropertyFound = true;
+ // foreach (var propertyInfo in props) {
+ // Console.WriteLine($"[!!] Known property {propertyInfo.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name} in {t.Name}!");
+ // }
+ }
+
+ if (unknownPropertyFound) Console.WriteLine(res.ToJson());
+ }
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs b/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
index 812c81c..a4b0791 100644
--- a/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
+++ b/MatrixRoomUtils.Core/Extensions/ObjectExtensions.cs
@@ -1,5 +1,7 @@
using System.Text.Encodings.Web;
using System.Text.Json;
+using MatrixRoomUtils.Core.Interfaces;
+using MatrixRoomUtils.Core.Responses;
namespace MatrixRoomUtils.Core.Extensions;
diff --git a/MatrixRoomUtils.Core/Helpers/SyncHelper.cs b/MatrixRoomUtils.Core/Helpers/SyncHelper.cs
index edbb646..04c31cd 100644
--- a/MatrixRoomUtils.Core/Helpers/SyncHelper.cs
+++ b/MatrixRoomUtils.Core/Helpers/SyncHelper.cs
@@ -1,5 +1,7 @@
+using System.Diagnostics.CodeAnalysis;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Interfaces;
using MatrixRoomUtils.Core.Responses;
using MatrixRoomUtils.Core.Services;
using MatrixRoomUtils.Core.StateEventTypes;
@@ -15,7 +17,7 @@ public class SyncHelper {
_storageService = storageService;
}
- public async Task<SyncResult?> Sync(string? since = null) {
+ public async Task<SyncResult?> Sync(string? since = null, CancellationToken? cancellationToken = null) {
var outFileName = "sync-" +
(await _storageService.CacheStorageProvider.GetAllKeys()).Count(x => x.StartsWith("sync")) +
".json";
@@ -23,12 +25,66 @@ public class SyncHelper {
if (!string.IsNullOrWhiteSpace(since)) url += $"&since={since}";
else url += "&full_state=true";
Console.WriteLine("Calling: " + url);
- var res = await _homeServer._httpClient.GetFromJsonAsync<SyncResult>(url);
- await _storageService.CacheStorageProvider.SaveObject(outFileName, res);
- return res;
+ try {
+ var res = await _homeServer._httpClient.GetFromJsonAsync<SyncResult>(url,
+ cancellationToken: cancellationToken ?? CancellationToken.None);
+ await _storageService.CacheStorageProvider.SaveObject(outFileName, res);
+ Console.WriteLine($"Wrote file: {outFileName}");
+ return res;
+ }
+ catch (TaskCanceledException) {
+ Console.WriteLine("Sync cancelled!");
+ }
+ catch (Exception e) {
+ Console.WriteLine(e);
+ }
+ return null;
+ }
+
+ [SuppressMessage("ReSharper", "FunctionNeverReturns")]
+ public async Task RunSyncLoop(CancellationToken? cancellationToken = null, bool skipInitialSyncEvents = true) {
+ SyncResult? sync = null;
+ while (cancellationToken is null || !cancellationToken.Value.IsCancellationRequested) {
+ sync = await Sync(sync?.NextBatch, cancellationToken);
+ Console.WriteLine($"Got sync, next batch: {sync?.NextBatch}!");
+ if (sync == null) continue;
+ if (sync.Rooms is { Invite.Count: > 0 }) {
+ foreach (var roomInvite in sync.Rooms.Invite) {
+ Console.WriteLine(roomInvite.Value.GetType().Name);
+ InviteReceived?.Invoke(this, roomInvite);
+ }
+ }
+
+ if (sync.AccountData is { Events: { Count: > 0 } }) {
+ foreach (var accountDataEvent in sync.AccountData.Events) {
+ AccountDataReceived?.Invoke(this, accountDataEvent);
+ }
+ }
+
+ // 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;
+ TimelineEventReceived?.Invoke(this, stateEventResponse);
+ }
+ }
+ }
+ }
}
-
- public event EventHandler<SyncResult>? ;
+
+ /// <summary>
+ /// Event fired when a room invite is received
+ /// </summary>
+ public event EventHandler<KeyValuePair<string, SyncResult.RoomsDataStructure.InvitedRoomDataStructure>>? InviteReceived;
+
+ public event EventHandler<StateEventResponse>? TimelineEventReceived;
+ public event EventHandler<StateEventResponse>? AccountDataReceived;
}
public class SyncResult {
@@ -36,30 +92,30 @@ public class SyncResult {
public string NextBatch { get; set; }
[JsonPropertyName("account_data")]
- public EventList AccountData { get; set; }
+ public EventList? AccountData { get; set; }
[JsonPropertyName("presence")]
- public PresenceDataStructure Presence { get; set; }
+ 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; }
+ public RoomsDataStructure? Rooms { get; set; }
// supporting classes
public class PresenceDataStructure {
[JsonPropertyName("events")]
- public List<StateEventResponse<PresenceStateEventData>> Events { get; set; }
+ public List<StateEventResponse> Events { get; set; }
}
public class RoomsDataStructure {
[JsonPropertyName("join")]
- public Dictionary<string, JoinedRoomDataStructure> Join { get; set; }
+ public Dictionary<string, JoinedRoomDataStructure>? Join { get; set; }
[JsonPropertyName("invite")]
- public Dictionary<string, InvitedRoomDataStructure> Invite { get; set; }
-
+ public Dictionary<string, InvitedRoomDataStructure>? Invite { get; set; }
+
public class JoinedRoomDataStructure {
[JsonPropertyName("timeline")]
public TimelineDataStructure Timeline { get; set; }
@@ -75,7 +131,7 @@ public class SyncResult {
[JsonPropertyName("unread_notifications")]
public UnreadNotificationsDataStructure UnreadNotifications { get; set; }
-
+
[JsonPropertyName("summary")]
public SummaryDataStructure Summary { get; set; }
@@ -97,12 +153,14 @@ public class SyncResult {
[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; }
}
diff --git a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
index c5645e6..fcff0f2 100644
--- a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
+++ b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
@@ -1,7 +1,7 @@
using System.Net.Http.Json;
using System.Text.Json;
using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Responses;
+using MatrixRoomUtils.Core.StateEventTypes;
namespace MatrixRoomUtils.Core.Interfaces;
@@ -91,7 +91,7 @@ public class IHomeServer {
}
_profileCache.Add(mxid, null);
- var resp = await _httpClient.GetAsync($"/_matrix/client/r0/profile/{mxid}");
+ var resp = await _httpClient.GetAsync($"/_matrix/client/v3/profile/{mxid}");
var data = await resp.Content.ReadFromJsonAsync<JsonElement>();
if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data);
var profile = data.Deserialize<ProfileResponse>();
@@ -99,5 +99,5 @@ public class IHomeServer {
return profile;
}
- public string? ResolveMediaUri(string mxc) => mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/r0/download/");
+ public string? ResolveMediaUri(string mxc) => mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/v3/download/");
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Interfaces/IStateEventType.cs b/MatrixRoomUtils.Core/Interfaces/IStateEventType.cs
new file mode 100644
index 0000000..053f50c
--- /dev/null
+++ b/MatrixRoomUtils.Core/Interfaces/IStateEventType.cs
@@ -0,0 +1,5 @@
+namespace MatrixRoomUtils.Core.Interfaces;
+
+public interface IStateEventType {
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/JoinRules.cs b/MatrixRoomUtils.Core/JoinRules.cs
new file mode 100644
index 0000000..7ce56c4
--- /dev/null
+++ b/MatrixRoomUtils.Core/JoinRules.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+
+namespace MatrixRoomUtils.Core;
+
+public class JoinRules {
+ 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/MatrixException.cs b/MatrixRoomUtils.Core/MatrixException.cs
index 3df70e1..50fae20 100644
--- a/MatrixRoomUtils.Core/MatrixException.cs
+++ b/MatrixRoomUtils.Core/MatrixException.cs
@@ -52,6 +52,6 @@ public class MatrixException : Exception {
"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()
+ _ => "Unknown error: " + new { ErrorCode, Error, SoftLogout, RetryAfterMs }.ToJson(ignoreNull: true)
};
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj b/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj
index 5ca40bd..a043378 100644
--- a/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj
+++ b/MatrixRoomUtils.Core/MatrixRoomUtils.Core.csproj
@@ -7,6 +7,9 @@
</PropertyGroup>
<ItemGroup>
+ <Reference Include="Microsoft.AspNetCore.Mvc.Core">
+ <HintPath>..\..\..\.cache\NuGetPackages\microsoft.aspnetcore.app.ref\7.0.5\ref\net7.0\Microsoft.AspNetCore.Mvc.Core.dll</HintPath>
+ </Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions">
<HintPath>..\..\..\.cache\NuGetPackages\microsoft.extensions.dependencyinjection.abstractions\7.0.0\lib\net7.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
diff --git a/MatrixRoomUtils.Core/MessagesResponse.cs b/MatrixRoomUtils.Core/MessagesResponse.cs
new file mode 100644
index 0000000..7a303bc
--- /dev/null
+++ b/MatrixRoomUtils.Core/MessagesResponse.cs
@@ -0,0 +1,19 @@
+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/Responses/CreateRoomRequest.cs b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
index da7d569..8719b5a 100644
--- a/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
+++ b/MatrixRoomUtils.Core/Responses/CreateRoomRequest.cs
@@ -1,8 +1,8 @@
-using System.Text.Json;
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;
namespace MatrixRoomUtils.Core.Responses;
@@ -20,6 +20,7 @@ public class CreateRoomRequest {
//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!;
@@ -47,237 +48,12 @@ public class CreateRoomRequest {
}
}
- //extra properties
- [JsonIgnore]
- public string HistoryVisibility {
- get {
- var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.history_visibility");
- if (stateEvent == null) {
- InitialState.Add(new StateEvent {
- Type = "m.room.history_visibility",
- Content = new JsonObject {
- ["history_visibility"] = "shared"
- }
- });
- return "shared";
- }
-
- return stateEvent.ContentAsJsonNode["history_visibility"].GetValue<string>();
- }
- set {
- var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.history_visibility");
- if (stateEvent == null)
- InitialState.Add(new StateEvent {
- Type = "m.room.history_visibility",
- Content = new JsonObject {
- ["history_visibility"] = value
- }
- });
- else {
- var v = stateEvent.ContentAsJsonNode;
- v["history_visibility"] = value;
- stateEvent.ContentAsJsonNode = v;
- }
- }
- }
-
- [JsonIgnore]
- public string RoomIcon {
- get {
- var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.avatar");
- if (stateEvent == null) {
- InitialState.Add(new StateEvent {
- Type = "m.room.avatar",
- Content = new JsonObject {
- ["url"] = ""
- }
- });
- return "";
- }
-
- return stateEvent.ContentAsJsonNode["url"].GetValue<string>();
- }
- set {
- var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.avatar");
- if (stateEvent == null)
- InitialState.Add(new StateEvent {
- Type = "m.room.avatar",
- Content = new JsonObject {
- ["url"] = value
- }
- });
- else {
- var v = stateEvent.ContentAsJsonNode;
- v["url"] = value;
- stateEvent.ContentAsJsonNode = v;
- }
- }
- }
-
- // [JsonIgnore]
- // public string GuestAccess
- // {
- // get
- // {
- // var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.guest_access");
- // if (stateEvent == null)
- // {
- // InitialState.Add(new StateEvent()
- // {
- // Type = "m.room.guest_access",
- // Content = new JsonObject()
- // {
- // ["guest_access"] = "can_join"
- // }
- // });
- // return "can_join";
- // }
- //
- // return stateEvent.ContentAsJsonNode["guest_access"].GetValue<string>();
- // }
- // set
- // {
- // var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.guest_access");
- // if (stateEvent == null)
- // {
- // InitialState.Add(new StateEvent()
- // {
- // Type = "m.room.guest_access",
- // Content = new JsonObject()
- // {
- // ["guest_access"] = value
- // }
- // });
- // }
- // else
- // {
- // var v = stateEvent.ContentAsJsonNode;
- // v["guest_access"] = value;
- // stateEvent.ContentAsJsonNode = v;
- // }
- // }
- // }
-
- public ServerACL ServerACLs {
- get {
- var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.server_acl");
- if (stateEvent == null) {
- InitialState.Add(new StateEvent {
- Type = "m.room.server_acl",
- Content = new JsonObject {
- ["allow"] = new JsonArray {
- "*"
- },
- ["deny"] = new JsonArray()
- }
- });
- return new ServerACL {
- Allow = new List<string> {
- "*"
- },
- Deny = new List<string>(),
- AllowIpLiterals = true
- };
- }
-
- return new ServerACL {
- Allow = stateEvent.ContentAsJsonNode["allow"].Deserialize<List<string>>(),
- Deny = stateEvent.ContentAsJsonNode["deny"].Deserialize<List<string>>(),
- AllowIpLiterals = true
- };
- }
- set {
- Console.WriteLine($"Setting server acl to {value.ToJson()}");
- var stateEvent = InitialState.FirstOrDefault(x => x.Type == "m.room.server_acl");
- if (stateEvent == null)
- InitialState.Add(new StateEvent {
- Type = "m.room.server_acl",
- Content = new JsonObject {
- ["allow"] = JsonNode.Parse(JsonSerializer.Serialize(value.Allow)),
- ["deny"] = JsonNode.Parse(JsonSerializer.Serialize(value.Deny))
- ["allow_ip_literals"] = value.AllowIpLiterals
- }
- });
- else {
- var v = stateEvent.ContentAsJsonNode;
- v["allow"] = JsonNode.Parse(JsonSerializer.Serialize(value.Allow));
- v["deny"] = JsonNode.Parse(JsonSerializer.Serialize(value.Deny));
- v["allow_ip_literals"] = value.AllowIpLiterals;
- stateEvent.ContentAsJsonNode = v;
- Console.WriteLine($"v={v.ToJson()}");
- Console.WriteLine($"stateEvent.ContentAsJsonNode={stateEvent.ContentAsJsonNode.ToJson()}");
- }
- }
- }
-
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.");
+ errors.Add("room_alias_name",
+ "Room alias name must only contain letters, numbers, underscores, and hyphens.");
return errors;
}
-}
-
-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;
- }
- }
-}
-
-public class PowerLevelEvent {
- [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;
-}
-
-public class NotificationsPL {
- [JsonPropertyName("room")]
- public int Room { get; set; } = 50;
-}
-
-public class ServerACL {
- [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/Responses/CreationContentBaseType.cs b/MatrixRoomUtils.Core/Responses/CreationContentBaseType.cs
new file mode 100644
index 0000000..743c552
--- /dev/null
+++ b/MatrixRoomUtils.Core/Responses/CreationContentBaseType.cs
@@ -0,0 +1,18 @@
+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
index 3259e44..8d0d94f 100644
--- a/MatrixRoomUtils.Core/Responses/LoginResponse.cs
+++ b/MatrixRoomUtils.Core/Responses/LoginResponse.cs
@@ -1,6 +1,7 @@
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.StateEventTypes;
namespace MatrixRoomUtils.Core.Responses;
@@ -19,7 +20,7 @@ public class LoginResponse {
public async Task<ProfileResponse> GetProfile() {
var hc = new HttpClient();
- var resp = await hc.GetAsync($"{HomeServer}/_matrix/client/r0/profile/{UserId}");
+ var resp = await hc.GetAsync($"{HomeServer}/_matrix/client/v3/profile/{UserId}");
var data = await resp.Content.ReadFromJsonAsync<JsonElement>();
if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data);
return data.Deserialize<ProfileResponse>();
diff --git a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
index 7b138e0..6e67887 100644
--- a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
+++ b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Interfaces;
namespace MatrixRoomUtils.Core.Responses;
@@ -26,7 +27,7 @@ public class StateEventResponse : StateEvent {
[JsonPropertyName("prev_content")]
public dynamic PrevContent { get; set; }
-
+
public class UnsignedData {
[JsonPropertyName("age")]
public ulong Age { get; set; }
@@ -40,9 +41,4 @@ public class StateEventResponse : StateEvent {
[JsonPropertyName("transaction_id")]
public string? TransactionId { get; set; }
}
-}
-
-public class StateEventResponse<T> : StateEventResponse where T : class {
- [JsonPropertyName("content")]
- public T Content { get; set; }
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Room.cs b/MatrixRoomUtils.Core/Room.cs
index 1568746..59c56ed 100644
--- a/MatrixRoomUtils.Core/Room.cs
+++ b/MatrixRoomUtils.Core/Room.cs
@@ -1,10 +1,8 @@
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
-using System.Text.Json.Serialization;
using System.Web;
using MatrixRoomUtils.Core.Extensions;
-using MatrixRoomUtils.Core.Responses;
using MatrixRoomUtils.Core.RoomTypes;
namespace MatrixRoomUtils.Core;
@@ -43,7 +41,7 @@ public class Room {
}
public async Task<MessagesResponse> GetMessagesAsync(string from = "", int limit = 10, string dir = "b", string filter = "") {
- var url = $"/_matrix/client/r0/rooms/{RoomId}/messages?from={from}&limit={limit}&dir={dir}";
+ 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.GetAsync(url);
if (!res.IsSuccessStatusCode) {
@@ -67,12 +65,14 @@ public class Room {
return resn;
}
- public async Task JoinAsync(string[]? homeservers = null) {
- var join_url = $"/_matrix/client/r0/join/{HttpUtility.UrlEncode(RoomId)}";
+ 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.PostAsync(fullJoinUrl, null);
+ var res = await _httpClient.PostAsJsonAsync(fullJoinUrl, new {
+ reason
+ });
}
public async Task<List<string>> GetMembersAsync(bool joinedOnly = true) {
@@ -138,7 +138,7 @@ public class Room {
var res = await GetStateAsync("m.room.create");
if (!res.HasValue) return new CreateEvent();
- res.FindExtraJsonFields(typeof(CreateEvent));
+ res.FindExtraJsonElementFields(typeof(CreateEvent));
return res.Value.Deserialize<CreateEvent>() ?? new CreateEvent();
}
@@ -151,7 +151,7 @@ public class Room {
}
public async Task ForgetAsync() {
- var res = await _httpClient.PostAsync($"/_matrix/client/r0/rooms/{RoomId}/forget", null);
+ var res = await _httpClient.PostAsync($"/_matrix/client/v3/rooms/{RoomId}/forget", null);
if (!res.IsSuccessStatusCode) {
Console.WriteLine($"Failed to forget room {RoomId} - got status: {res.StatusCode}");
throw new Exception($"Failed to forget room {RoomId} - got status: {res.StatusCode}");
@@ -159,7 +159,9 @@ public class Room {
}
public async Task LeaveAsync(string? reason = null) {
- var res = await _httpClient.PostAsync($"/_matrix/client/r0/rooms/{RoomId}/leave", string.IsNullOrWhiteSpace(reason) ? null : new StringContent($"{{\"reason\":\"{reason}\"}}", Encoding.UTF8, "application/json"));
+ var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/leave", new {
+ reason
+ });
if (!res.IsSuccessStatusCode) {
Console.WriteLine($"Failed to leave room {RoomId} - got status: {res.StatusCode}");
throw new Exception($"Failed to leave room {RoomId} - got status: {res.StatusCode}");
@@ -168,7 +170,7 @@ public class Room {
public async Task KickAsync(string userId, string? reason = null) {
- var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/r0/rooms/{RoomId}/kick", new UserIdAndReason() { user_id = userId, reason = reason });
+ var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/kick", new UserIdAndReason() { UserId = userId, Reason = reason });
if (!res.IsSuccessStatusCode) {
Console.WriteLine($"Failed to kick {userId} from room {RoomId} - got status: {res.StatusCode}");
throw new Exception($"Failed to kick {userId} from room {RoomId} - got status: {res.StatusCode}");
@@ -176,7 +178,7 @@ public class Room {
}
public async Task BanAsync(string userId, string? reason = null) {
- var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/r0/rooms/{RoomId}/ban", new UserIdAndReason() { user_id = userId, reason = reason });
+ var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/ban", new UserIdAndReason() { UserId = userId, Reason = reason });
if (!res.IsSuccessStatusCode) {
Console.WriteLine($"Failed to ban {userId} from room {RoomId} - got status: {res.StatusCode}");
throw new Exception($"Failed to ban {userId} from room {RoomId} - got status: {res.StatusCode}");
@@ -184,61 +186,31 @@ public class Room {
}
public async Task UnbanAsync(string userId) {
- var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/r0/rooms/{RoomId}/unban", new UserIdAndReason() { user_id = userId });
+ var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/unban", new UserIdAndReason() { UserId = userId });
if (!res.IsSuccessStatusCode) {
Console.WriteLine($"Failed to unban {userId} from room {RoomId} - got status: {res.StatusCode}");
throw new Exception($"Failed to unban {userId} from room {RoomId} - got status: {res.StatusCode}");
}
}
+ public async Task<EventIdResponse> SendStateEventAsync(string eventType, object content) {
+ var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType}", content);
+ if (!res.IsSuccessStatusCode) {
+ Console.WriteLine($"Failed to send state event {eventType} to room {RoomId} - got status: {res.StatusCode}");
+ throw new Exception($"Failed to send state event {eventType} to room {RoomId} - got status: {res.StatusCode}");
+ }
+ return await res.Content.ReadFromJsonAsync<EventIdResponse>();
+ }
+
+ public async Task<EventIdResponse> SendMessageEventAsync(string eventType, object content) {
+ var res = await _httpClient.PutAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/"+new Guid(), content);
+ if (!res.IsSuccessStatusCode) {
+ Console.WriteLine($"Failed to send event {eventType} to room {RoomId} - got status: {res.StatusCode}");
+ throw new Exception($"Failed to send event {eventType} to room {RoomId} - got status: {res.StatusCode}");
+ }
+ return await res.Content.ReadFromJsonAsync<EventIdResponse>();
+ }
public readonly SpaceRoom AsSpace;
-}
-
-internal class UserIdAndReason {
- public string user_id { get; set; }
- public string? reason { get; set; }
-}
-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();
-}
-
-public class CreateEvent {
- [JsonPropertyName("creator")]
- public string Creator { get; set; }
-
- [JsonPropertyName("room_version")]
- public string RoomVersion { get; set; }
-
- [JsonPropertyName("type")]
- public string? Type { get; set; }
-
- [JsonPropertyName("predecessor")]
- public object? Predecessor { get; set; }
-
- [JsonPropertyName("m.federate")]
- public bool Federate { get; set; }
-}
-
-public class JoinRules {
- private const string Public = "public";
- private const string Invite = "invite";
- private const 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/RoomTypes/SpaceRoom.cs b/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
index 7f634dc..6eaa73b 100644
--- a/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
+++ b/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
@@ -1,5 +1,6 @@
using System.Text.Json;
using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
using MatrixRoomUtils.Core.Responses;
namespace MatrixRoomUtils.Core.RoomTypes;
@@ -11,10 +12,10 @@ public class SpaceRoom : Room {
var rooms = new List<Room>();
var state = await GetStateAsync("");
if (state != null) {
- var states = state.Value.Deserialize<StateEventResponse<object>[]>()!;
+ var states = state.Value.Deserialize<StateEventResponse[]>()!;
foreach (var stateEvent in states.Where(x => x.Type == "m.space.child")) {
var roomId = stateEvent.StateKey;
- if(stateEvent.Content.ToJson() != "{}" || includeRemoved)
+ if(stateEvent.TypedContent.ToJson() != "{}" || includeRemoved)
rooms.Add(await RuntimeCache.CurrentHomeServer.GetRoom(roomId));
}
}
diff --git a/MatrixRoomUtils.Core/RuntimeCache.cs b/MatrixRoomUtils.Core/RuntimeCache.cs
index db71ee5..7ab3952 100644
--- a/MatrixRoomUtils.Core/RuntimeCache.cs
+++ b/MatrixRoomUtils.Core/RuntimeCache.cs
@@ -1,5 +1,6 @@
using MatrixRoomUtils.Core.Extensions;
using MatrixRoomUtils.Core.Responses;
+using MatrixRoomUtils.Core.StateEventTypes;
namespace MatrixRoomUtils.Core;
diff --git a/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs b/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs
index 3db4584..0f09a45 100644
--- a/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs
+++ b/MatrixRoomUtils.Core/Services/HomeserverProviderService.cs
@@ -1,5 +1,3 @@
-using MatrixRoomUtils.Core.Attributes;
-
namespace MatrixRoomUtils.Core.Services;
public class HomeserverProviderService {
@@ -13,6 +11,6 @@ public class HomeserverProviderService {
}
public async Task<AuthenticatedHomeServer> GetAuthenticatedWithToken(string homeserver, string accessToken) {
- return await new AuthenticatedHomeServer(homeserver, accessToken, _tieredStorageService).Configure();
+ return await new AuthenticatedHomeServer(_tieredStorageService, homeserver, accessToken).Configure();
}
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Services/ServiceInstaller.cs b/MatrixRoomUtils.Core/Services/ServiceInstaller.cs
index 43255d8..1b275c5 100644
--- a/MatrixRoomUtils.Core/Services/ServiceInstaller.cs
+++ b/MatrixRoomUtils.Core/Services/ServiceInstaller.cs
@@ -1,16 +1,27 @@
-using MatrixRoomUtils.Core.Interfaces.Services;
using Microsoft.Extensions.DependencyInjection;
namespace MatrixRoomUtils.Core.Services;
public static class ServiceInstaller {
- public static IServiceCollection AddRoryLibMatrixServices(this IServiceCollection services) {
+ 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 != null)
+ services.AddSingleton(config);
+ else {
+ services.AddSingleton(new RoryLibMatrixConfiguration());
+ }
+ //Add services
services.AddScoped<HomeserverProviderService>();
return services;
}
+}
+
+public class RoryLibMatrixConfiguration {
+ public string AppName { get; set; } = "Rory&::LibMatrix";
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEvent.cs b/MatrixRoomUtils.Core/StateEvent.cs
index a8c1fac..cb8f0b4 100644
--- a/MatrixRoomUtils.Core/StateEvent.cs
+++ b/MatrixRoomUtils.Core/StateEvent.cs
@@ -1,12 +1,20 @@
+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;
namespace MatrixRoomUtils.Core;
public class StateEvent {
- [JsonPropertyName("content")]
- public dynamic Content { get; set; } = new { };
+ public static List<Type> KnownStateEventTypes =
+ new ClassCollector<IStateEventType>().ResolveFromAllAccessibleAssemblies();
+
+ public object TypedContent {
+ get => RawContent.Deserialize(GetType)!;
+ set => RawContent = JsonSerializer.Deserialize<JsonObject>(JsonSerializer.Serialize(value));
+ }
[JsonPropertyName("state_key")]
public string StateKey { get; set; } = "";
@@ -17,35 +25,40 @@ public class StateEvent {
[JsonPropertyName("replaces_state")]
public string? ReplacesState { get; set; }
- //extra properties
+ [JsonPropertyName("content")]
+ public JsonObject? RawContent { get; set; }
+
+ public T1 GetContent<T1>() where T1 : IStateEventType {
+ return RawContent.Deserialize<T1>();
+ }
+
[JsonIgnore]
- public JsonNode ContentAsJsonNode {
- get => JsonSerializer.SerializeToNode(Content);
- set => Content = value;
+ public Type GetType {
+ get {
+ var type = StateEvent.KnownStateEventTypes.FirstOrDefault(x =>
+ x.GetCustomAttribute<MatrixEventAttribute>()?.EventName == Type);
+ if (type == null) {
+ Console.WriteLine($"Warning: unknown event type '{Type}'!");
+ Console.WriteLine(RawContent.ToJson());
+ return typeof(object);
+ }
+
+ RawContent.FindExtraJsonObjectFields(type);
+
+ return type;
+ }
}
+ //debug
public string dtype {
get {
var res = GetType().Name switch {
- "StateEvent`1" => $"StateEvent<{Content.GetType().Name}>",
+ "StateEvent`1" => $"StateEvent",
_ => GetType().Name
};
return res;
}
}
- public StateEvent<T> As<T>() where T : class => (StateEvent<T>)this;
-}
-
-public class StateEvent<T> : StateEvent where T : class {
- public StateEvent() {
- //import base content if not an empty object
- if (base.Content.GetType() == typeof(T)) {
- Console.WriteLine($"StateEvent<{typeof(T)}> created with base content of type {base.Content.GetType()}. Importing base content.");
- Content = base.Content;
- }
- }
-
- [JsonPropertyName("content")]
- public new T Content { get; set; }
+ public string cdtype => TypedContent.GetType().Name;
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/CanonicalAliasEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/CanonicalAliasEventData.cs
new file mode 100644
index 0000000..2f9502e
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/CanonicalAliasEventData.cs
@@ -0,0 +1,11 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.canonical_alias")]
+public class CanonicalAliasEventData : IStateEventType {
+ [JsonPropertyName("alias")]
+ public string? Alias { get; set; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/GuestAccessData.cs b/MatrixRoomUtils.Core/StateEventTypes/GuestAccessData.cs
new file mode 100644
index 0000000..1727ce9
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/GuestAccessData.cs
@@ -0,0 +1,16 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.guest_access")]
+public class GuestAccessData : 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/HistoryVisibilityData.cs b/MatrixRoomUtils.Core/StateEventTypes/HistoryVisibilityData.cs
new file mode 100644
index 0000000..481cc08
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/HistoryVisibilityData.cs
@@ -0,0 +1,9 @@
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.history_visibility")]
+public class HistoryVisibilityData : IStateEventType {
+ public string HistoryVisibility { get; set; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/MemberEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/MemberEventData.cs
new file mode 100644
index 0000000..acf7777
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/MemberEventData.cs
@@ -0,0 +1,23 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.member")]
+public class MemberEventData : 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; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/MessageEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/MessageEventData.cs
new file mode 100644
index 0000000..ad99709
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/MessageEventData.cs
@@ -0,0 +1,11 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+[MatrixEvent(EventName = "m.room.message")]
+public class MessageEventData : IStateEventType {
+ [JsonPropertyName("body")]
+ public string Body { get; set; }
+ [JsonPropertyName("msgtype")]
+ public string MessageType { get; set; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs
index 6f6d082..e67639b 100644
--- a/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs
+++ b/MatrixRoomUtils.Core/StateEventTypes/PolicyRuleStateEventData.cs
@@ -1,8 +1,9 @@
using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Interfaces;
namespace MatrixRoomUtils.Core.StateEventTypes;
-public class PolicyRuleStateEventData {
+public class PolicyRuleStateEventData : IStateEventType {
/// <summary>
/// Entity this ban applies to, can use * and ? as globs.
/// </summary>
diff --git a/MatrixRoomUtils.Core/StateEventTypes/PowerLevelEvent.cs b/MatrixRoomUtils.Core/StateEventTypes/PowerLevelEvent.cs
new file mode 100644
index 0000000..a3e44d1
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/PowerLevelEvent.cs
@@ -0,0 +1,43 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.power_levels")]
+public class PowerLevelEvent : 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;
+
+ public class NotificationsPL {
+ [JsonPropertyName("room")]
+ public int Room { get; set; } = 50;
+ }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/PresenceStateEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/PresenceStateEventData.cs
index d835c95..a17b6f9 100644
--- a/MatrixRoomUtils.Core/StateEventTypes/PresenceStateEventData.cs
+++ b/MatrixRoomUtils.Core/StateEventTypes/PresenceStateEventData.cs
@@ -1,8 +1,11 @@
using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
namespace MatrixRoomUtils.Core.StateEventTypes;
-public class PresenceStateEventData {
+[MatrixEvent(EventName = "m.presence")]
+public class PresenceStateEventData : IStateEventType {
[JsonPropertyName("presence")]
public string Presence { get; set; }
[JsonPropertyName("last_active_ago")]
diff --git a/MatrixRoomUtils.Core/Responses/ProfileResponse.cs b/MatrixRoomUtils.Core/StateEventTypes/ProfileResponse.cs
index db72386..d36ef74 100644
--- a/MatrixRoomUtils.Core/Responses/ProfileResponse.cs
+++ b/MatrixRoomUtils.Core/StateEventTypes/ProfileResponse.cs
@@ -1,7 +1,9 @@
using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
-namespace MatrixRoomUtils.Core.Responses;
+namespace MatrixRoomUtils.Core.StateEventTypes;
+[MatrixEvent(EventName = "m.room.member")]
public class ProfileResponse {
[JsonPropertyName("avatar_url")]
public string? AvatarUrl { get; set; } = "";
diff --git a/MatrixRoomUtils.Core/StateEventTypes/RoomAvatarEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/RoomAvatarEventData.cs
new file mode 100644
index 0000000..03ce16b
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/RoomAvatarEventData.cs
@@ -0,0 +1,18 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[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 {
+
+ }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/RoomTopicEventData.cs b/MatrixRoomUtils.Core/StateEventTypes/RoomTopicEventData.cs
new file mode 100644
index 0000000..72651c8
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/RoomTopicEventData.cs
@@ -0,0 +1,11 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.topic")]
+public class RoomTopicEventData : IStateEventType {
+ [JsonPropertyName("topic")]
+ public string? Topic { get; set; }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/StateEventTypes/ServerACLData.cs b/MatrixRoomUtils.Core/StateEventTypes/ServerACLData.cs
new file mode 100644
index 0000000..41bf0a8
--- /dev/null
+++ b/MatrixRoomUtils.Core/StateEventTypes/ServerACLData.cs
@@ -0,0 +1,17 @@
+using System.Text.Json.Serialization;
+using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Interfaces;
+
+namespace MatrixRoomUtils.Core.StateEventTypes;
+
+[MatrixEvent(EventName = "m.room.server_acl")]
+public class ServerACLData : 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/UserIdAndReason.cs b/MatrixRoomUtils.Core/UserIdAndReason.cs
new file mode 100644
index 0000000..3801077
--- /dev/null
+++ b/MatrixRoomUtils.Core/UserIdAndReason.cs
@@ -0,0 +1,10 @@
+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
diff --git a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs
index 878eca4..59ec4db 100644
--- a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs
+++ b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs
@@ -21,7 +21,7 @@ public class LocalStorageWrapper {
Console.WriteLine("Access token is not null, creating authenticated home server");
Console.WriteLine($"Homeserver cache: {RuntimeCache.HomeserverResolutionCache.Count} entries");
// Console.WriteLine(RuntimeCache.HomeserverResolutionCache.ToJson());
- RuntimeCache.CurrentHomeServer = await new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.HomeServer, RuntimeCache.LastUsedToken, TODO).Configure();
+ RuntimeCache.CurrentHomeServer = await new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.HomeServer, RuntimeCache.LastUsedToken, null).Configure();
Console.WriteLine("Created authenticated home server");
}
}
diff --git a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
index 77c8281..47844e3 100644
--- a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
+++ b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
@@ -1,6 +1,7 @@
using System.Text.Json.Nodes;
using MatrixRoomUtils.Core;
using MatrixRoomUtils.Core.Responses;
+using MatrixRoomUtils.Core.StateEventTypes;
namespace MatrixRoomUtils.Web.Classes.RoomCreationTemplates;
@@ -18,9 +19,9 @@ public class DefaultRoomCreationTemplate : IRoomCreationTemplate {
history_visibility = "world_readable"
}
},
- new StateEvent<Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent> {
+ new StateEvent<GuestAccessData> {
Type = "m.room.guest_access",
- Content = new Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent {
+ Content = new GuestAccessData {
GuestAccess = "can_join"
}
},
diff --git a/MatrixRoomUtils.Web/Pages/DebugTools.razor b/MatrixRoomUtils.Web/Pages/DebugTools.razor
index da5c172..4e4cec8 100644
--- a/MatrixRoomUtils.Web/Pages/DebugTools.razor
+++ b/MatrixRoomUtils.Web/Pages/DebugTools.razor
@@ -1,6 +1,5 @@
@page "/Debug"
@using System.Reflection
-@using MatrixRoomUtils.Core.Extensions
@using MatrixRoomUtils.Core.Interfaces
@inject ILocalStorageService LocalStorage
@inject NavigationManager NavigationManager
diff --git a/MatrixRoomUtils.Web/Pages/DevOptions.razor b/MatrixRoomUtils.Web/Pages/DevOptions.razor
index 0843d5f..cdb5693 100644
--- a/MatrixRoomUtils.Web/Pages/DevOptions.razor
+++ b/MatrixRoomUtils.Web/Pages/DevOptions.razor
@@ -1,5 +1,4 @@
@page "/DevOptions"
-@using MatrixRoomUtils.Core.Extensions
@inject NavigationManager NavigationManager
@inject ILocalStorageService LocalStorage
diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
index 1fe13bd..858fad9 100644
--- a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
+++ b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
@@ -1,5 +1,4 @@
@page "/HSAdmin/RoomQuery"
-@using MatrixRoomUtils.Core.Extensions
@using MatrixRoomUtils.Core.Filters
@using MatrixRoomUtils.Core.Responses.Admin
@using MatrixRoomUtils.Web.Shared.SimpleComponents
diff --git a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
index 8031146..80dbfd1 100644
--- a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
+++ b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
@@ -1,6 +1,5 @@
@page "/KnownHomeserverList"
@using System.Text.Json
-@using MatrixRoomUtils.Core.Extensions
@using System.Diagnostics
@using MatrixRoomUtils.Core.Responses
<h3>Known Homeserver List</h3>
diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor
index 3b78817..9df7fa6 100644
--- a/MatrixRoomUtils.Web/Pages/LoginPage.razor
+++ b/MatrixRoomUtils.Web/Pages/LoginPage.razor
@@ -52,7 +52,7 @@
var userinfo = new UserInfo {
LoginResponse = result
};
- userinfo.Profile = await (await new AuthenticatedHomeServer(result.HomeServer, result.AccessToken, TODO).Configure()).GetProfile(result.UserId);
+ userinfo.Profile = await RuntimeCache.CurrentHomeServer.GetProfile(result.UserId);
RuntimeCache.LastUsedToken = result.AccessToken;
RuntimeCache.LoginSessions.Add(result.AccessToken, userinfo);
diff --git a/MatrixRoomUtils.Web/Pages/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/MediaLocator.razor
index 36cd8e6..38d1514 100644
--- a/MatrixRoomUtils.Web/Pages/MediaLocator.razor
+++ b/MatrixRoomUtils.Web/Pages/MediaLocator.razor
@@ -61,7 +61,7 @@
await sem.WaitAsync();
var httpClient = new HttpClient { BaseAddress = new Uri(hs) };
httpClient.Timeout = TimeSpan.FromSeconds(5);
- var rmu = mxcUrl.Replace("mxc://", $"{hs}/_matrix/media/r0/download/");
+ var rmu = mxcUrl.Replace("mxc://", $"{hs}/_matrix/media/v3/download/");
try {
var res = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, rmu));
if (res.IsSuccessStatusCode) {
diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
index 76b4384..0840ebf 100644
--- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
+++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
@@ -1,5 +1,4 @@
@page "/PolicyListEditor/{RoomId}"
-@using MatrixRoomUtils.Core.Extensions
@using MatrixRoomUtils.Core.StateEventTypes
@using System.Text.Json
@using MatrixRoomUtils.Core.Responses
@@ -210,7 +209,7 @@ else {
private async Task LoadStatesAsync() {
// using var client = new HttpClient();
// client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken);
- // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state");
+ // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/rooms/{RoomId}/state");
// var Content = await response.Content.ReadAsStringAsync();
// Console.WriteLine(JsonSerializer.Deserialize<object>(Content).ToJson());
// var stateEvents = JsonSerializer.Deserialize<List<StateEventResponse>>(Content);
diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
index 20eab7a..8f711b5 100644
--- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
+++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
@@ -1,5 +1,4 @@
@page "/PolicyListEditor"
-@using MatrixRoomUtils.Core.Extensions
@inject ILocalStorageService LocalStorage
@inject NavigationManager NavigationManager
<h3>Policy list editor - Room list</h3>
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
index 5cfda77..80d852a 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
@@ -1,9 +1,8 @@
@page "/RoomManagerCreateRoom"
-@using MatrixRoomUtils.Core.Extensions
@using MatrixRoomUtils.Core.Responses
@using System.Text.Json
-@using System.Text.Json.Serialization
@using System.Reflection
+@using MatrixRoomUtils.Core.StateEventTypes
@using MatrixRoomUtils.Web.Classes.RoomCreationTemplates
@* ReSharper disable once RedundantUsingDirective - Must not remove this, Rider marks this as "unused" when it's not *@
@using MatrixRoomUtils.Web.Shared.SimpleComponents
@@ -53,12 +52,12 @@
<tr>
<td style="padding-top: 16px;">History visibility:</td>
<td style="padding-top: 16px;">
- <InputSelect @bind-Value="@creationEvent.HistoryVisibility">
- <option value="invited">Invited</option>
- <option value="joined">Joined</option>
- <option value="shared">Shared</option>
- <option value="world_readable">World readable</option>
- </InputSelect>
+ @* <InputSelect @bind-Value="@creationEvent.HistoryVisibility"> *@
+ @* <option value="invited">Invited</option> *@
+ @* <option value="joined">Joined</option> *@
+ @* <option value="shared">Shared</option> *@
+ @* <option value="world_readable">World readable</option> *@
+ @* </InputSelect> *@
</td>
</tr>
<tr>
@@ -220,15 +219,15 @@
OverwriteWrappedPropertiesFromEvent();
creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
- guestAccessEvent = creationEvent["m.room.guest_access"].As<GuestAccessContent>().Content;
+ guestAccessEvent = creationEvent["m.room.guest_access"].As<GuestAccessData>().Content;
Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}");
- Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessContent>().ToJson()}");
- creationEvent["m.room.guest_access"].As<GuestAccessContent>().Content.IsGuestAccessEnabled = true;
+ Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}");
+ creationEvent["m.room.guest_access"].As<GuestAccessData>().Content.IsGuestAccessEnabled = true;
Console.WriteLine("-- Created new guest access content --");
Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}");
- Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessContent>().ToJson()}");
- Console.WriteLine($"Creation event casted back: {creationEvent["m.room.guest_access"].As<GuestAccessContent>().ToJson()}");
+ Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}");
+ Console.WriteLine($"Creation event casted back: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}");
StateHasChanged();
}
}
@@ -236,7 +235,7 @@
private Dictionary<string, string> creationEventValidationErrors { get; set; } = new();
private CreateRoomRequest creationEvent { get; set; }
- GuestAccessContent guestAccessEvent { get; set; }
+ GuestAccessData guestAccessEvent { get; set; }
private Dictionary<string, CreateRoomRequest> Presets { get; set; } = new();
@@ -275,7 +274,7 @@
Console.WriteLine("Overwriting wrapped properties");
Console.WriteLine($"Allow: {ServerACLAllowRules.Count}: {string.Join(", ", ServerACLAllowRules)}");
Console.WriteLine($"Deny: {ServerACLDenyRules.Count}: {string.Join(", ", ServerACLDenyRules)}");
- creationEvent.ServerACLs = new ServerACL {
+ creationEvent.ServerACLs = new ServerACLData {
Allow = ServerACLAllowRules,
Deny = ServerACLDenyRules,
AllowIpLiterals = creationEvent.ServerACLs.AllowIpLiterals
@@ -336,14 +335,5 @@
_ => key
};
- public class GuestAccessContent {
- [JsonPropertyName("guest_access")]
- public string GuestAccess { get; set; }
-
- public bool IsGuestAccessEnabled {
- get => GuestAccess == "can_join";
- set => GuestAccess = value ? "can_join" : "forbidden";
- }
- }
}
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
index ab650d1..a9c71c4 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
@@ -1,5 +1,4 @@
@page "/RoomManager/Space/{RoomId}"
-@using MatrixRoomUtils.Core.Extensions
@using System.Text.Json
@using MatrixRoomUtils.Core.Responses
<h3>Room manager - Viewing Space</h3>
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
index fa5b6a8..296514c 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
@@ -63,7 +63,7 @@
using var client = new HttpClient();
//TODO: can this be improved?
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken);
- var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state");
+ var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/v3/rooms/{RoomId}/state");
// var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
//var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>();
var _data = await response.Content.ReadAsStreamAsync();
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
index bfd4d10..ff1d9ac 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
@@ -1,5 +1,4 @@
@page "/RoomStateViewer/{RoomId}"
-@using MatrixRoomUtils.Core.Extensions
@using System.Net.Http.Headers
@using System.Text.Json
@inject ILocalStorageService LocalStorage
@@ -88,7 +87,7 @@
//TODO: can we improve this?
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken);
- var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state");
+ var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/v3/rooms/{RoomId}/state");
// var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
//var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>();
var _data = await response.Content.ReadAsStreamAsync();
diff --git a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor
index 8ab44fb..975da43 100644
--- a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor
+++ b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor
@@ -22,12 +22,13 @@
private int _roomCount { get; set; } = 0;
protected override async Task OnInitializedAsync() {
- var hs = await new AuthenticatedHomeServer(User.LoginResponse.HomeServer, User.AccessToken, TODO).Configure();
+ await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
+
if (User.Profile.AvatarUrl != null && User.Profile.AvatarUrl != "")
- _avatarUrl = hs.ResolveMediaUri(User.Profile.AvatarUrl);
+ _avatarUrl = RuntimeCache.CurrentHomeServer.ResolveMediaUri(User.Profile.AvatarUrl);
else _avatarUrl = "https://api.dicebear.com/6.x/identicon/svg?seed=" + User.LoginResponse.UserId;
try {
- _roomCount = (await hs.GetJoinedRooms()).Count;
+ _roomCount = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Count;
}
catch {
_roomCount = -1;
diff --git a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
index 43a4111..0a58b4d 100644
--- a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
+++ b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
@@ -36,13 +36,11 @@
await _semaphoreSlim.WaitAsync();
- var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.HomeServerDomain, RuntimeCache.CurrentHomeServer.AccessToken, TODO).Configure();
-
if (User == null) {
if (UserId == null) {
throw new ArgumentNullException(nameof(UserId));
}
- User = await hs.GetProfile(UserId);
+ User = await RuntimeCache.CurrentHomeServer.GetProfile(UserId);
}
// UserId = User.;
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor
index 42a5f64..ea7d2ec 100644
--- a/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor
@@ -1,4 +1,3 @@
-@using MatrixRoomUtils.Core.Extensions
<table>
@foreach (var i in Items.Keys) {
var key = i;
diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
index 4fb5596..f89dc44 100644
--- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
+++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
@@ -1,22 +1,21 @@
-@using MatrixRoomUtils.Core.Extensions
-@if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "ban") {
+@if (Event.membership"]!.GetValue<string>() == "ban") {
<i>@Event.StateKey was banned</i>
}
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "invite") {
+else if (Event.membership"]!.GetValue<string>() == "invite") {
<i>@Event.StateKey was invited</i>
}
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "join") {
+else if (Event.membership"]!.GetValue<string>() == "join") {
@if (Event.ReplacesState != null) {
- <i>@Event.StateKey changed their display name to @(Event.ContentAsJsonNode["displayname"]!.GetValue<string>())</i>
+ <i>@Event.StateKey changed their display name to @(Event.displayname"]!.GetValue<string>())</i>
}
else {
<i><InlineUserItem UserId="@Event.StateKey"></InlineUserItem> joined</i>
}
}
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "leave") {
+else if (Event.membership"]!.GetValue<string>() == "leave") {
<i>@Event.StateKey left</i>
}
-else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "knock") {
+else if (Event.membership"]!.GetValue<string>() == "knock") {
<i>@Event.StateKey knocked</i>
}
else {
diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
index 80a432b..6c26dc2 100644
--- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
+++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
@@ -1,4 +1,3 @@
-@using MatrixRoomUtils.Core.Extensions
@using MatrixRoomUtils.Core.Responses
<pre>
@ObjectExtensions.ToJson(Event.Content, indent: false)
diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor
index f78bdc9..d8ea7e2 100644
--- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor
+++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor
@@ -1,4 +1,3 @@
-@using MatrixRoomUtils.Core.Extensions
<div>
<details style="display: inline;">
diff --git a/MatrixRoomUtils.Web/Shared/UserListItem.razor b/MatrixRoomUtils.Web/Shared/UserListItem.razor
index b99671a..52f398a 100644
--- a/MatrixRoomUtils.Web/Shared/UserListItem.razor
+++ b/MatrixRoomUtils.Web/Shared/UserListItem.razor
@@ -25,7 +25,7 @@
private string? profileAvatar { get; set; } = "/icon-192.png";
private string? profileName { get; set; } = "Loading...";
- private static SemaphoreSlim _semaphoreSlim = new(128);
+ private static SemaphoreSlim _semaphoreSlim = new(8);
protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync();
@@ -33,13 +33,11 @@
await _semaphoreSlim.WaitAsync();
- var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.HomeServerDomain, RuntimeCache.CurrentHomeServer.AccessToken, TODO).Configure();
-
if (User == null) {
if (UserId == null) {
throw new ArgumentNullException(nameof(UserId));
}
- User = await hs.GetProfile(UserId);
+ User = await RuntimeCache.CurrentHomeServer.GetProfile(UserId);
}
// UserId = User.;
diff --git a/MatrixRoomUtils.Web/wwwroot/css/app.css b/MatrixRoomUtils.Web/wwwroot/css/app.css
index cb7ba63..b3a8cf3 100644
--- a/MatrixRoomUtils.Web/wwwroot/css/app.css
+++ b/MatrixRoomUtils.Web/wwwroot/css/app.css
@@ -74,7 +74,7 @@ a, .btn-link {
}
.blazor-error-boundary {
- background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
+ background: url(data:image/svg+xml;base64,PHN2ZyB3aWv3aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
diff --git a/MatrixRoomUtils.sln b/MatrixRoomUtils.sln
index a29cf89..a29cf89 100644..100755
--- a/MatrixRoomUtils.sln
+++ b/MatrixRoomUtils.sln
diff --git a/MatrixRoomUtils.sln.DotSettings.user b/MatrixRoomUtils.sln.DotSettings.user
index 033da4f..93b1fca 100644
--- a/MatrixRoomUtils.sln.DotSettings.user
+++ b/MatrixRoomUtils.sln.DotSettings.user
@@ -1,7 +1,15 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
- <s:String x:Key="/Default/CodeInspection/Highlighting/SweaWarningsMode/@EntryValue">ShowAndRun</s:String>
+ <s:String x:Key="/Default/CodeInspection/Highlighting/SweaWarningsMode/@EntryValue">DoNotShowAndRun</s:String>
+ <s:Int64 x:Key="/Default/Environment/Hierarchy/Build/BuildTool/MsBuildSolutionLoadingNodeCount/@EntryValue">12</s:Int64>
+ <s:Boolean x:Key="/Default/Environment/Hierarchy/Build/BuildTool/MsBuildSolutionLoadingOrderingEnabled/@EntryValue">True</s:Boolean>
+ <s:String x:Key="/Default/Environment/Hierarchy/Build/SolBuilderDuo/UseMsbuildSolutionBuilder/@EntryValue">No</s:String>
+ <s:Int64 x:Key="/Default/Environment/Hierarchy/Build/SolutionBuilderNext/ParallelProcessesCount2/@EntryValue">12</s:Int64>
+
+ <s:Boolean x:Key="/Default/Environment/Hierarchy/Build/SolutionBuilderNext/ShouldRestoreNugetPackages/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UnloadedProject/UnloadedProjects/=244e90fe_002Dee26_002D4f78_002D86eb_002D27529ae48905_0023MatrixRoomUtils/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UnloadedProject/UnloadedProjects/=d38da95d_002Ddd83_002D4340_002D96a4_002D6f59fc6ae3d9_0023MatrixRoomUtils_002EWeb/@EntryIndexedValue">True</s:Boolean>
+
+
<s:Boolean x:Key="/Default/UnloadedProject/UnloadedProjects/=f997f26f_002D2ec1_002D4d18_002Db3dd_002Dc46fb2ad65c0_0023MatrixRoomUtils_002EWeb_002EServer/@EntryIndexedValue">True</s:Boolean>
@@ -10,4 +18,10 @@
+
+
+
+
+
+
</wpf:ResourceDictionary>
\ No newline at end of file
|