about summary refs log tree commit diff
path: root/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj4
-rw-r--r--Utilities/LibMatrix.DevTestBot/Bot/Commands/DbgAniRainbowTest.cs1
-rw-r--r--Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs13
-rw-r--r--Utilities/LibMatrix.DevTestBot/Bot/DevTestBot.cs2
-rw-r--r--Utilities/LibMatrix.DevTestBot/Bot/Interfaces/CommandContext.cs9
-rw-r--r--Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs125
-rw-r--r--Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj6
-rw-r--r--Utilities/LibMatrix.DevTestBot/Program.cs2
-rw-r--r--Utilities/LibMatrix.DevTestBot/appsettings.json4
-rw-r--r--Utilities/LibMatrix.E2eeTestKit/LibMatrix.E2eeTestKit.csproj6
-rw-r--r--Utilities/LibMatrix.E2eeTestKit/Pages/CSTJTest.razor1
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs13
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs93
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/HEAdmin/HEAdminController.cs18
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/HEClient/HEClientController.cs34
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/HEDebug/HEDebugController.cs34
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/LegacyController.cs6
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs14
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomMembersController.cs2
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs28
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs3
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs50
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/AccountDataController.cs4
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/FilterController.cs4
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/ProfileController.cs4
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/UserController.cs6
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs7
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs64
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj6
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Program.cs9
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Services/HSEConfiguration.cs18
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Services/MediaStore.cs16
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Services/PaginationTokenResolverService.cs6
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs69
-rw-r--r--Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs20
-rw-r--r--Utilities/LibMatrix.TestDataGenerator/LibMatrix.TestDataGenerator.csproj6
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs18
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Commands/AliassesCommand.cs1
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Commands/HelpCommand.cs3
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Interfaces/ICommand.cs4
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj6
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs1
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs3
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Services/InviteListenerHostedService.cs6
44 files changed, 493 insertions, 256 deletions
diff --git a/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj b/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj

index f21b34d..ee4fd58 100644 --- a/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj +++ b/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj
@@ -9,8 +9,8 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" /> - <PackageReference Include="Swashbuckle.AspNetCore" Version="7.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.1" /> + <PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" /> </ItemGroup> <ItemGroup> diff --git a/Utilities/LibMatrix.DevTestBot/Bot/Commands/DbgAniRainbowTest.cs b/Utilities/LibMatrix.DevTestBot/Bot/Commands/DbgAniRainbowTest.cs
index f75c863..c91261f 100644 --- a/Utilities/LibMatrix.DevTestBot/Bot/Commands/DbgAniRainbowTest.cs +++ b/Utilities/LibMatrix.DevTestBot/Bot/Commands/DbgAniRainbowTest.cs
@@ -2,7 +2,6 @@ using System.Diagnostics; using LibMatrix.EventTypes.Spec; using LibMatrix.ExampleBot.Bot.Interfaces; using LibMatrix.Helpers; -using LibMatrix.RoomTypes; using LibMatrix.Services; namespace ModerationBot.Commands; diff --git a/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs b/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs
index 85c86a3..745c75d 100644 --- a/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs +++ b/Utilities/LibMatrix.DevTestBot/Bot/Commands/PingCommand.cs
@@ -7,5 +7,16 @@ public class PingCommand : ICommand { public string Name { get; } = "ping"; public string Description { get; } = "Pong!"; - public async Task Invoke(CommandContext ctx) => await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "pong!")); + // public async Task Invoke(CommandContext ctx) => await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "pong!")); + public async Task Invoke(CommandContext ctx) { + // await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "pong!")); + var count = ctx.Args.Length > 0 ? int.Parse(ctx.Args[0]) : 1; + var tasks = Enumerable.Range(0, count).Select(async i => { + await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: $"!ping {i}", messageType: "m.text")); + await Task.Delay(1000); + }).ToList(); + await Task.WhenAll(tasks); + + await ctx.Room.SendMessageEventAsync(new RoomMessageEventContent(body: "Pong!")); + } } \ No newline at end of file diff --git a/Utilities/LibMatrix.DevTestBot/Bot/DevTestBot.cs b/Utilities/LibMatrix.DevTestBot/Bot/DevTestBot.cs
index fa80bfd..c650e2b 100644 --- a/Utilities/LibMatrix.DevTestBot/Bot/DevTestBot.cs +++ b/Utilities/LibMatrix.DevTestBot/Bot/DevTestBot.cs
@@ -1,7 +1,7 @@ using System.Diagnostics.CodeAnalysis; using ArcaneLibs.Extensions; using LibMatrix.EventTypes.Spec; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.ExampleBot.Bot.Interfaces; using LibMatrix.Helpers; using LibMatrix.Homeservers; diff --git a/Utilities/LibMatrix.DevTestBot/Bot/Interfaces/CommandContext.cs b/Utilities/LibMatrix.DevTestBot/Bot/Interfaces/CommandContext.cs
index 90a95e4..221d1f4 100644 --- a/Utilities/LibMatrix.DevTestBot/Bot/Interfaces/CommandContext.cs +++ b/Utilities/LibMatrix.DevTestBot/Bot/Interfaces/CommandContext.cs
@@ -4,8 +4,9 @@ using LibMatrix.RoomTypes; namespace LibMatrix.ExampleBot.Bot.Interfaces; public class CommandContext { - public GenericRoom Room { get; set; } - public StateEventResponse MessageEvent { get; set; } - public string CommandName => (MessageEvent.TypedContent as RoomMessageEventContent).Body.Split(' ')[0][1..]; - public string[] Args => (MessageEvent.TypedContent as RoomMessageEventContent).Body.Split(' ')[1..]; + public required GenericRoom Room { get; init; } + public required StateEventResponse MessageEvent { get; init; } + public string CommandName => MessageContent.Body.Split(' ')[0][1..]; + public string[] Args => MessageContent.Body.Split(' ')[1..]; + private RoomMessageEventContent MessageContent => MessageEvent.TypedContent as RoomMessageEventContent ?? throw new Exception("Message content is not a RoomMessageEventContent"); } \ No newline at end of file diff --git a/Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs b/Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs new file mode 100644
index 0000000..9c8ad67 --- /dev/null +++ b/Utilities/LibMatrix.DevTestBot/Bot/PingTestBot.cs
@@ -0,0 +1,125 @@ +using System.Diagnostics.CodeAnalysis; +using ArcaneLibs.Extensions; +using LibMatrix.EventTypes.Spec; +using LibMatrix.EventTypes.Spec.State.RoomInfo; +using LibMatrix.ExampleBot.Bot.Interfaces; +using LibMatrix.Filters; +using LibMatrix.Helpers; +using LibMatrix.Homeservers; +using LibMatrix.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace LibMatrix.ExampleBot.Bot; + +public class PingTestBot : IHostedService { + private readonly HomeserverProviderService _homeserverProviderService; + private readonly ILogger<DevTestBot> _logger; + private readonly DevTestBotConfiguration _configuration; + private readonly IEnumerable<ICommand> _commands; + + public PingTestBot(HomeserverProviderService homeserverProviderService, ILogger<DevTestBot> logger, + DevTestBotConfiguration configuration, IServiceProvider services) { + logger.LogInformation("{} instantiated!", GetType().Name); + _homeserverProviderService = homeserverProviderService; + _logger = logger; + _configuration = configuration; + _logger.LogInformation("Getting commands..."); + _commands = services.GetServices<ICommand>(); + _logger.LogInformation("Got {} commands!", _commands.Count()); + } + + /// <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) { + // Directory.GetFiles("bot_data/cache").ToList().ForEach(File.Delete); + AuthenticatedHomeserverGeneric hs; + try { + hs = await _homeserverProviderService.GetAuthenticatedWithToken(_configuration.Homeserver, + _configuration.AccessToken); + } + catch (Exception e) { + _logger.LogError("{}", e.Message); + throw; + } + + var msg = new MessageBuilder().WithRainbowString("Meanwhile, I'm sitting here, still struggling with trying to rainbow. ^^'").Build(); + + var syncHelper = new SyncHelper(hs); + syncHelper.Filter = new SyncFilter { + Room = new SyncFilter.RoomFilter { + Timeline = new SyncFilter.RoomFilter.StateFilter() { + Limit = 1, + Senders = ["@me"] + }, + Rooms = ["!ping-v11:maunium.net"], + AccountData = new(types: []), + IncludeLeave = false + } + }; + + // await hs.GetRoom("!VJwxdebqoQlhGSEncc:codestorm.net").JoinAsync(); + + // foreach (var room in await hs.GetJoinedRooms()) { + // if(room.RoomId is "!OGEhHVWSdvArJzumhm:matrix.org") continue; + // foreach (var stateEvent in await room.GetStateAsync<List<StateEvent>>("")) { + // var _ = stateEvent.GetType; + // } + // _logger.LogInformation($"Got room state for {room.RoomId}!"); + // } + + // syncHelper.InviteReceivedHandlers.Add(async Task (args) => { + // var inviteEvent = + // args.Value.InviteState.Events.FirstOrDefault(x => + // x.Type == "m.room.member" && x.StateKey == hs.UserId); + // _logger.LogInformation( + // $"Got invite to {args.Key} by {inviteEvent.Sender} with reason: {(inviteEvent.TypedContent as RoomMemberEventContent).Reason}"); + // if (inviteEvent.Sender.EndsWith(":rory.gay") || inviteEvent.Sender == "@mxidupwitch:the-apothecary.club") + // try { + // var senderProfile = await hs.GetProfileAsync(inviteEvent.Sender); + // await hs.GetRoom(args.Key).JoinAsync(reason: $"I was invited by {senderProfile.DisplayName ?? inviteEvent.Sender}!"); + // } + // catch (Exception e) { + // _logger.LogError("{}", e.ToString()); + // await hs.GetRoom(args.Key).LeaveAsync("I was unable to join the room: " + e); + // } + // }); + syncHelper.TimelineEventHandlers.Add(async @event => { + _logger.LogInformation( + "Got timeline event in {}: {}", @event.RoomId, @event.ToJson(false, true)); + + var room = hs.GetRoom(@event.RoomId); + // _logger.LogInformation(eventResponse.ToJson(indent: false)); + if (@event is not { Sender: "@emma:rory.gay" }) return; + if (@event is { Type: "m.room.message", TypedContent: RoomMessageEventContent message }) + if (message is { MessageType: "m.text" } && message.Body.StartsWith(_configuration.Prefix)) { + var command = _commands.FirstOrDefault(x => x.Name == message.Body.Split(' ')[0][_configuration.Prefix.Length..]); + if (command == null) { + await room.SendMessageEventAsync( + new RoomMessageEventContent("m.text", "Command not found!")); + return; + } + + var ctx = new CommandContext { + Room = room, + MessageEvent = @event + }; + if (await command.CanInvoke(ctx)) + await command.Invoke(ctx); + else + await room.SendMessageEventAsync( + new RoomMessageEventContent("m.text", "You do not have permission to run this command!")); + } + }); + await syncHelper.RunSyncLoopAsync(cancellationToken: cancellationToken); + } + + /// <summary>Triggered when the application host is performing a graceful shutdown.</summary> + /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param> + public Task StopAsync(CancellationToken cancellationToken) { + _logger.LogInformation("Shutting down bot!"); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj b/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj
index e6ab408..7897e28 100644 --- a/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj +++ b/Utilities/LibMatrix.DevTestBot/LibMatrix.DevTestBot.csproj
@@ -18,13 +18,15 @@ </PropertyGroup> <ItemGroup> + <PackageReference Include="ArcaneLibs.StringNormalisation" Version="1.0.0-preview.20250307-202359" Condition="'$(Configuration)' == 'Release'" /> + <ProjectReference Include="..\..\ArcaneLibs\ArcaneLibs.StringNormalisation\ArcaneLibs.StringNormalisation.csproj" Condition="'$(Configuration)' == 'Debug'"/> <ProjectReference Include="..\..\LibMatrix\LibMatrix.csproj"/> </ItemGroup> <ItemGroup> - <PackageReference Include="ArcaneLibs.StringNormalisation" Version="1.0.0-1.0.0-preview.20241122-053825"/> - <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" /> + <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1"/> </ItemGroup> + <ItemGroup> <Content Include="appsettings*.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> diff --git a/Utilities/LibMatrix.DevTestBot/Program.cs b/Utilities/LibMatrix.DevTestBot/Program.cs
index daaa65e..8eaaea8 100644 --- a/Utilities/LibMatrix.DevTestBot/Program.cs +++ b/Utilities/LibMatrix.DevTestBot/Program.cs
@@ -24,7 +24,7 @@ var host = Host.CreateDefaultBuilder(args).ConfigureServices((_, services) => { } // services.AddHostedService<ServerRoomSizeCalulator>(); - services.AddHostedService<DevTestBot>(); + services.AddHostedService<PingTestBot>(); }).UseConsoleLifetime().Build(); await host.RunAsync(); \ No newline at end of file diff --git a/Utilities/LibMatrix.DevTestBot/appsettings.json b/Utilities/LibMatrix.DevTestBot/appsettings.json
index db64c22..0d18b81 100644 --- a/Utilities/LibMatrix.DevTestBot/appsettings.json +++ b/Utilities/LibMatrix.DevTestBot/appsettings.json
@@ -8,7 +8,7 @@ }, "Bot": { "Homeserver": "rory.gay", - "AccessToken": "syt_xxxxxxxxxxxxxxxxx", - "Prefix": "!" + "AccessToken": "syt_ZW1tYQ_ATWykhpCWzjxkgTJHnAx_2AaoI7", + "Prefix": "$" } } \ No newline at end of file diff --git a/Utilities/LibMatrix.E2eeTestKit/LibMatrix.E2eeTestKit.csproj b/Utilities/LibMatrix.E2eeTestKit/LibMatrix.E2eeTestKit.csproj
index 4e3a128..78cdb67 100644 --- a/Utilities/LibMatrix.E2eeTestKit/LibMatrix.E2eeTestKit.csproj +++ b/Utilities/LibMatrix.E2eeTestKit/LibMatrix.E2eeTestKit.csproj
@@ -1,15 +1,15 @@ <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> + <TargetFramework>net9.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest> </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.6" /> - <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.6" PrivateAssets="all" /> + <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.1" /> + <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.1" PrivateAssets="all" /> </ItemGroup> <ItemGroup> diff --git a/Utilities/LibMatrix.E2eeTestKit/Pages/CSTJTest.razor b/Utilities/LibMatrix.E2eeTestKit/Pages/CSTJTest.razor
index 0d01428..2b787b3 100644 --- a/Utilities/LibMatrix.E2eeTestKit/Pages/CSTJTest.razor +++ b/Utilities/LibMatrix.E2eeTestKit/Pages/CSTJTest.razor
@@ -1,6 +1,5 @@ @page "/CSTJTest" @using System.Text.Json -@using System.Text.Json.Nodes @using LibMatrix.Extensions <PageTitle>Counter</PageTitle> diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs
index 5550c26..d0eaed4 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs
@@ -1,26 +1,21 @@ -using System.Security.Cryptography; using System.Text.Json.Nodes; using LibMatrix.HomeserverEmulator.Services; using LibMatrix.Responses; -using LibMatrix.Services; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; [ApiController] [Route("/_matrix/client/{version}/")] -public class AuthController(ILogger<AuthController> logger, UserStore userStore, TokenService tokenService, HSEConfiguration config) : ControllerBase { +public class AuthController(ILogger<AuthController> logger, UserStore userStore, TokenService tokenService, HseConfiguration config) : ControllerBase { [HttpPost("login")] public async Task<LoginResponse> Login(LoginRequest request) { if (!request.Identifier.User.StartsWith('@')) request.Identifier.User = $"@{request.Identifier.User}:{tokenService.GenerateServerName(HttpContext)}"; - if (request.Identifier.User.EndsWith("localhost")) - request.Identifier.User = request.Identifier.User.Replace("localhost", tokenService.GenerateServerName(HttpContext)); + // if (request.Identifier.User.EndsWith("localhost")) + // request.Identifier.User = request.Identifier.User.Replace("localhost", tokenService.GenerateServerName(HttpContext)); - var user = await userStore.GetUserById(request.Identifier.User); - if (user is null) { - user = await userStore.CreateUser(request.Identifier.User); - } + var user = await userStore.GetUserById(request.Identifier.User) ?? await userStore.CreateUser(request.Identifier.User); return user.Login(); } diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs
index b29edf5..d497ca6 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs
@@ -1,11 +1,9 @@ -using System.Text.Json.Nodes; using System.Text.Json.Serialization; using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Services; using LibMatrix.Homeservers; using LibMatrix.Responses; -using LibMatrix.Services; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; @@ -35,6 +33,70 @@ public class DirectoryController(ILogger<DirectoryController> logger, RoomStore }; } + [HttpGet("client/v3/publicRooms")] + public async Task<PublicRoomDirectoryResult> GetPublicRooms(int limit = 100, string? server = null, string? since = null) { + var rooms = roomStore._rooms.OrderByDescending(x => x.JoinedMembers.Count).AsEnumerable(); + + if (since != null) { + rooms = rooms.SkipWhile(x => x.RoomId != since).Skip(1); + } + + if (server != null) { + rooms = rooms.Where(x => x.State.Any(y => y.Type == RoomMemberEventContent.EventId && y.StateKey!.EndsWith(server))); + } + + var count = rooms.Count(); + rooms = rooms.Take(limit); + + return new PublicRoomDirectoryResult() { + Chunk = rooms.Select(x => new PublicRoomDirectoryResult.PublicRoomListItem() { + RoomId = x.RoomId, + Name = x.State.FirstOrDefault(y => y.Type == RoomNameEventContent.EventId)?.RawContent?["name"]?.ToString(), + Topic = x.State.FirstOrDefault(y => y.Type == RoomTopicEventContent.EventId)?.RawContent?["topic"]?.ToString(), + AvatarUrl = x.State.FirstOrDefault(y => y.Type == RoomAvatarEventContent.EventId)?.RawContent?["url"]?.ToString(), + GuestCanJoin = x.State.Any(y => y.Type == RoomGuestAccessEventContent.EventId && y.RawContent?["guest_access"]?.ToString() == "can_join"), + NumJoinedMembers = x.JoinedMembers.Count, + WorldReadable = x.State.Any(y => y.Type == RoomHistoryVisibilityEventContent.EventId && y.RawContent?["history_visibility"]?.ToString() == "world_readable"), + JoinRule = x.State.FirstOrDefault(y => y.Type == RoomJoinRulesEventContent.EventId)?.RawContent?["join_rule"]?.ToString(), + CanonicalAlias = x.State.FirstOrDefault(y => y.Type == RoomCanonicalAliasEventContent.EventId)?.RawContent?["alias"]?.ToString() + }).ToList(), + NextBatch = count > limit ? rooms.Last().RoomId : null, + TotalRoomCountEstimate = count + }; + } + + [HttpPost("client/v3/publicRooms")] + public async Task<PublicRoomDirectoryResult> GetFilteredPublicRooms([FromBody] PublicRoomDirectoryRequest request, [FromQuery] string? server = null) { + var rooms = roomStore._rooms.OrderByDescending(x => x.JoinedMembers.Count).AsEnumerable(); + + if (request.Since != null) { + rooms = rooms.SkipWhile(x => x.RoomId != request.Since).Skip(1); + } + + if (server != null) { + rooms = rooms.Where(x => x.State.Any(y => y.Type == RoomMemberEventContent.EventId && y.StateKey!.EndsWith(server))); + } + + var count = rooms.Count(); + rooms = rooms.Take(request.Limit ?? 100); + + return new PublicRoomDirectoryResult() { + Chunk = rooms.Select(x => new PublicRoomDirectoryResult.PublicRoomListItem() { + RoomId = x.RoomId, + Name = x.State.FirstOrDefault(y => y.Type == RoomNameEventContent.EventId)?.RawContent?["name"]?.ToString(), + Topic = x.State.FirstOrDefault(y => y.Type == RoomTopicEventContent.EventId)?.RawContent?["topic"]?.ToString(), + AvatarUrl = x.State.FirstOrDefault(y => y.Type == RoomAvatarEventContent.EventId)?.RawContent?["url"]?.ToString(), + GuestCanJoin = x.State.Any(y => y.Type == RoomGuestAccessEventContent.EventId && y.RawContent?["guest_access"]?.ToString() == "can_join"), + NumJoinedMembers = x.JoinedMembers.Count, + WorldReadable = x.State.Any(y => y.Type == RoomHistoryVisibilityEventContent.EventId && y.RawContent?["history_visibility"]?.ToString() == "world_readable"), + JoinRule = x.State.FirstOrDefault(y => y.Type == RoomJoinRulesEventContent.EventId)?.RawContent?["join_rule"]?.ToString(), + CanonicalAlias = x.State.FirstOrDefault(y => y.Type == RoomCanonicalAliasEventContent.EventId)?.RawContent?["alias"]?.ToString() + }).ToList(), + NextBatch = count > request.Limit ? rooms.Last().RoomId : null, + TotalRoomCountEstimate = count + }; + } + #endregion #region User directory @@ -64,4 +126,29 @@ public class DirectoryController(ILogger<DirectoryController> logger, RoomStore } #endregion +} + +public class PublicRoomDirectoryRequest { + [JsonPropertyName("filter")] + public PublicRoomDirectoryFilter Filter { get; set; } + + [JsonPropertyName("include_all_networks")] + public bool IncludeAllNetworks { get; set; } + + [JsonPropertyName("limit")] + public int? Limit { get; set; } + + [JsonPropertyName("since")] + public string? Since { get; set; } + + [JsonPropertyName("third_party_instance_id")] + public string? ThirdPartyInstanceId { get; set; } + + public class PublicRoomDirectoryFilter { + [JsonPropertyName("generic_search_term")] + public string? GenericSearchTerm { get; set; } + + [JsonPropertyName("room_types")] + public List<string>? RoomTypes { get; set; } + } } \ No newline at end of file diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEAdmin/HEAdminController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEAdmin/HEAdminController.cs new file mode 100644
index 0000000..1fb3251 --- /dev/null +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEAdmin/HEAdminController.cs
@@ -0,0 +1,18 @@ +using LibMatrix.HomeserverEmulator.Services; +using Microsoft.AspNetCore.Mvc; + +namespace LibMatrix.HomeserverEmulator.Controllers; + +[ApiController] +[Route("/_hse/admin")] +public class HEAdminController(ILogger<HEAdminController> logger, UserStore userStore, RoomStore roomStore) : ControllerBase { + [HttpGet("users")] + public async Task<List<UserStore.User>> GetUsers() { + return userStore._users.ToList(); + } + + [HttpGet("rooms")] + public async Task<List<RoomStore.Room>> GetRooms() { + return roomStore._rooms.ToList(); + } +} \ No newline at end of file diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEClient/HEClientController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEClient/HEClientController.cs new file mode 100644
index 0000000..85e4ddb --- /dev/null +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEClient/HEClientController.cs
@@ -0,0 +1,34 @@ +using ArcaneLibs.Collections; +using LibMatrix.HomeserverEmulator.Services; +using LibMatrix.Responses; +using Microsoft.AspNetCore.Mvc; + +namespace LibMatrix.HomeserverEmulator.Controllers; + +[ApiController] +[Route("/_hse/client/v1/external_profiles")] +public class HEClientController(ILogger<HEClientController> logger, UserStore userStore, TokenService tokenService) : ControllerBase { + [HttpGet] + public async Task<ObservableDictionary<string, LoginResponse>> GetExternalProfiles() { + var token = tokenService.GetAccessToken(HttpContext); + var user = await userStore.GetUserByToken(token); + + return user.AuthorizedSessions; + } + + [HttpPut("{name}")] + public async Task PutExternalProfile(string name, [FromBody] LoginResponse sessionData) { + var token = tokenService.GetAccessToken(HttpContext); + var user = await userStore.GetUserByToken(token); + + user.AuthorizedSessions[name] = sessionData; + } + + [HttpDelete("{name}")] + public async Task DeleteExternalProfile(string name) { + var token = tokenService.GetAccessToken(HttpContext); + var user = await userStore.GetUserByToken(token); + + user.AuthorizedSessions.Remove(name); + } +} \ No newline at end of file diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEDebug/HEDebugController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEDebug/HEDebugController.cs
index 9e0c17c..ce47245 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEDebug/HEDebugController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/HEDebug/HEDebugController.cs
@@ -1,18 +1,18 @@ -using LibMatrix.HomeserverEmulator.Services; -using Microsoft.AspNetCore.Mvc; - -namespace LibMatrix.HomeserverEmulator.Controllers; - -[ApiController] -[Route("/_hsEmulator")] -public class HEDebugController(ILogger<HEDebugController> logger, UserStore userStore, RoomStore roomStore) : ControllerBase { - [HttpGet("users")] - public async Task<List<UserStore.User>> GetUsers() { - return userStore._users.ToList(); - } - - [HttpGet("rooms")] - public async Task<List<RoomStore.Room>> GetRooms() { - return roomStore._rooms.ToList(); - } +using LibMatrix.HomeserverEmulator.Services; +using Microsoft.AspNetCore.Mvc; + +namespace LibMatrix.HomeserverEmulator.Controllers; + +[ApiController] +[Route("/_hsEmulator")] +public class HEDebugController(ILogger<HEDebugController> logger, UserStore userStore, RoomStore roomStore) : ControllerBase { + [HttpGet("users")] + public async Task<List<UserStore.User>> GetUsers() { + return userStore._users.ToList(); + } + + [HttpGet("rooms")] + public async Task<List<RoomStore.Room>> GetRooms() { + return roomStore._rooms.ToList(); + } } \ No newline at end of file diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/LegacyController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/LegacyController.cs
index 1fb427e..245770e 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/LegacyController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/LegacyController.cs
@@ -1,12 +1,8 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Security.Cryptography; -using System.Text.Json.Nodes; using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Services; -using LibMatrix.Responses; -using LibMatrix.Services; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs
index 59d37ff..6048bbb 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Media/MediaController.cs
@@ -1,9 +1,9 @@ using System.Text.Json.Nodes; using System.Text.RegularExpressions; -using ArcaneLibs.Collections; using LibMatrix.HomeserverEmulator.Services; using LibMatrix.Services; using Microsoft.AspNetCore.Mvc; +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member namespace LibMatrix.HomeserverEmulator.Controllers.Media; @@ -13,12 +13,12 @@ public class MediaController( ILogger<MediaController> logger, TokenService tokenService, UserStore userStore, - HSEConfiguration cfg, + HseConfiguration cfg, HomeserverResolverService hsResolver, MediaStore mediaStore) : ControllerBase { [HttpPost("upload")] - public async Task<object> UploadMedia([FromHeader(Name = "Content-Type")] string ContentType, [FromQuery] string filename, [FromBody] Stream file) { + public async Task<object> UploadMedia([FromHeader(Name = "Content-Type")] string contentType, [FromQuery] string filename, [FromBody] Stream file) { var token = tokenService.GetAccessTokenOrNull(HttpContext); if (token == null) throw new MatrixException() { @@ -76,7 +76,9 @@ public class MediaController( if (cfg.StoreData) { var path = Path.Combine(cfg.DataStoragePath, "media", serverName, mediaId); if (!System.IO.File.Exists(path)) { - var mediaUrl = await hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + // var mediaUrl = await hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + var homeserver = (await hsResolver.ResolveHomeserverFromWellKnown(serverName)).Client; + var mediaUrl = homeserver is null ? null : $"{homeserver}/_matrix/media/v3/download/"; if (mediaUrl is null) throw new MatrixException() { ErrorCode = "M_NOT_FOUND", @@ -91,7 +93,9 @@ public class MediaController( return new FileStream(path, FileMode.Open); } else { - var mediaUrl = await hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + // var mediaUrl = await hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + var homeserver = (await hsResolver.ResolveHomeserverFromWellKnown(serverName)).Client; + var mediaUrl = homeserver is null ? null : $"{homeserver}/_matrix/media/v3/download/"; if (mediaUrl is null) throw new MatrixException() { ErrorCode = "M_NOT_FOUND", diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomMembersController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomMembersController.cs
index 7d735f7..6c57cc4 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomMembersController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomMembersController.cs
@@ -1,4 +1,4 @@ -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Services; using Microsoft.AspNetCore.Mvc; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
index 7a16ace..61195b8 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
@@ -1,10 +1,10 @@ -using System.Collections.Immutable; using System.Diagnostics; using System.Text.Json.Nodes; using ArcaneLibs; using ArcaneLibs.Extensions; using LibMatrix.EventTypes.Spec; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; +using LibMatrix.EventTypes.Spec.State.Space; using LibMatrix.Helpers; using LibMatrix.HomeserverEmulator.Extensions; using LibMatrix.HomeserverEmulator.Services; @@ -21,6 +21,7 @@ public class RoomTimelineController( TokenService tokenService, UserStore userStore, RoomStore roomStore, + HseConfiguration hseConfig, HomeserverProviderService hsProvider) : ControllerBase { [HttpPut("send/{eventType}/{txnId}")] public async Task<EventIdResponse> SendMessage(string roomId, string eventType, string txnId, [FromBody] JsonObject content) { @@ -34,21 +35,21 @@ public class RoomTimelineController( Error = "Room not found" }; - if (!room.JoinedMembers.Any(x => x.StateKey == user.UserId)) - throw new MatrixException() { - ErrorCode = "M_FORBIDDEN", - Error = "User is not in the room" - }; - var evt = new StateEvent() { RawContent = content, Type = eventType }.ToStateEvent(user, room); - room.Timeline.Add(evt); if (evt.Type == RoomMessageEventContent.EventId && (evt.TypedContent as RoomMessageEventContent).Body.StartsWith("!hse")) _ = Task.Run(() => HandleHseCommand(evt, room, user)); - // else + + if (!room.JoinedMembers.Any(x => x.StateKey == user.UserId)) + throw new MatrixException() { + ErrorCode = "M_FORBIDDEN", + Error = "User is not in the room" + }; + + room.Timeline.Add(evt); return new() { EventId = evt.EventId @@ -256,7 +257,8 @@ public class RoomTimelineController( room.Timeline.Add(new StateEventResponse() { Type = RoomMessageEventContent.EventId, TypedContent = content, - Sender = $"@hse:{tokenService.GenerateServerName(HttpContext)}", + // Sender = $"@hse:{tokenService.GenerateServerName(HttpContext)}", + Sender = $"@hse:{hseConfig.ServerName}", RoomId = room.RoomId, EventId = "$" + string.Join("", Random.Shared.GetItems("abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789".ToCharArray(), 100)), OriginServerTs = DateTimeOffset.Now.ToUnixTimeMilliseconds() @@ -299,7 +301,7 @@ public class RoomTimelineController( InternalSendMessage(room, url + "&i=" + i); if (i % 5000 == 0 || i == 9999) { - Thread.Sleep(5000); + // Thread.Sleep(1000); do { InternalSendMessage(room, @@ -320,7 +322,7 @@ public class RoomTimelineController( var count = 1000; for (int i = 0; i < count; i++) { var crq = new CreateRoomRequest() { - Name = "Test room", + Name = $"Test room {i}", CreationContent = new() { ["version"] = "11" }, diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs
index c24e6e9..9dae2e5 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs
@@ -1,5 +1,4 @@ using System.Text.Json.Serialization; -using LibMatrix.EventTypes.Spec.State; using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Services; using LibMatrix.Responses; @@ -62,7 +61,7 @@ public class RoomsController(ILogger<RoomsController> logger, TokenService token var room = new RoomStore.Room($"!{Guid.NewGuid()}:{tokenService.GenerateServerName(HttpContext)}"); var eventTypesToTransfer = new[] { - RoomServerACLEventContent.EventId, + RoomServerAclEventContent.EventId, RoomEncryptionEventContent.EventId, RoomNameEventContent.EventId, RoomAvatarEventContent.EventId, diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs
index f585eed..86c9f6a 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs
@@ -1,7 +1,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Extensions; using LibMatrix.HomeserverEmulator.Services; using LibMatrix.Responses; @@ -11,7 +11,7 @@ namespace LibMatrix.HomeserverEmulator.Controllers; [ApiController] [Route("/_matrix/client/{version}/")] -public class SyncController(ILogger<SyncController> logger, TokenService tokenService, UserStore userStore, RoomStore roomStore, HSEConfiguration cfg) : ControllerBase { +public class SyncController(ILogger<SyncController> logger, TokenService tokenService, UserStore userStore, RoomStore roomStore, HseConfiguration cfg) : ControllerBase { [HttpGet("sync")] [SuppressMessage("ReSharper.DPA", "DPA0011: High execution time of MVC action", Justification = "Endpoint is expected to wait until data is available or timeout.")] public async Task<SyncResponse> Sync([FromQuery] string? since = null, [FromQuery] int? timeout = 5000) { @@ -34,10 +34,18 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe newSyncState = syncState.Clone(); var newSyncToken = Guid.NewGuid().ToString(); + long stallTime = 100; do { syncResp = IncrementalSync(user, session, syncState); syncResp.NextBatch = newSyncToken; - } while (!await HasDataOrStall(syncResp) && sw.ElapsedMilliseconds < timeout); + + var hasData = await HasDataOrStall(syncResp); + if (!hasData) { + await Task.Delay((int)Math.Min(stallTime, Math.Max(0, (timeout ?? 10) - sw.ElapsedMilliseconds))); + stallTime *= 2; + } + else break; + } while (sw.ElapsedMilliseconds < timeout); if (sw.ElapsedMilliseconds > timeout) { logger.LogTrace("Sync timed out after {Elapsed}", sw.Elapsed); @@ -49,6 +57,7 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe session.SyncStates[syncResp.NextBatch] = RecalculateSyncStates(newSyncState, syncResp); logger.LogTrace("Responding to sync after {totalElapsed}", sw.Elapsed); + // logger.LogTrace(syncResp.ToJson(ignoreNull: true)); return syncResp; } @@ -135,6 +144,7 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe }; // step 1: check previously synced rooms + int updatedRooms = 0; foreach (var (roomId, roomPosition) in syncState.RoomPositions) { var room = roomStore.GetRoomById(roomId); if (room == null) { @@ -147,9 +157,11 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe var newTimelineEvents = room.Timeline.Skip(roomPosition.TimelinePosition).ToList(); var newAccountDataEvents = room.AccountData[user.UserId].Skip(roomPosition.AccountDataPosition).ToList(); if (newTimelineEvents.Count == 0 && newAccountDataEvents.Count == 0) continue; + if (updatedRooms++ >= 50) break; // performance cap data.Join[room.RoomId] = new() { State = new(newTimelineEvents.GetCalculatedState()), - Timeline = new(newTimelineEvents, false) + Timeline = new(newTimelineEvents, false), + AccountData = new(newAccountDataEvents) }; } } @@ -160,11 +172,11 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe } // step 2: check newly joined rooms - var untrackedRooms = roomStore._rooms.Where(r => !syncState.RoomPositions.ContainsKey(r.RoomId)).ToList(); + // var untrackedRooms = roomStore._rooms.Where(r => !syncState.RoomPositions.ContainsKey(r.RoomId)).ToList(); var allJoinedRooms = roomStore.GetRoomsByMember(user.UserId).ToArray(); if (allJoinedRooms.Length == 0) return data; - var rooms = Random.Shared.GetItems(allJoinedRooms, Math.Min(allJoinedRooms.Length, 50)); + var rooms = Random.Shared.GetItems(allJoinedRooms, Math.Min(allJoinedRooms.Length, 1)); foreach (var membership in rooms) { var membershipContent = membership.TypedContent as RoomMemberEventContent ?? throw new InvalidOperationException("Membership event content is not RoomMemberEventContent"); @@ -211,7 +223,7 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe private bool HasData(SyncResponse resp) { return resp.Rooms?.Invite?.Count > 0 || resp.Rooms?.Join?.Count > 0 || resp.Rooms?.Leave?.Count > 0; } - + private async Task<bool> HasDataOrStall(SyncResponse resp) { // logger.LogTrace("Checking if sync response has data: {resp}", resp.ToJson(indent: false, ignoreNull: true)); // if (resp.AccountData?.Events?.Count > 0) return true; @@ -246,29 +258,23 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe // }; var hasData = resp is { - AccountData: { - Events: { Count: > 0 } - } + AccountData.Events.Count: > 0 } or { - Presence: { - Events: { Count: > 0 } - } + Presence.Events.Count: > 0 } or { DeviceLists: { - Changed: { Count: > 0 }, - Left: { Count: > 0 } + Changed.Count: > 0, + Left.Count: > 0 } } or { - ToDevice: { - Events: { Count: > 0 } - } + ToDevice.Events.Count: > 0 } or { Rooms: { - Invite: { Count: > 0 } + Invite.Count: > 0 } or { - Join: { Count: > 0 } + Join.Count: > 0 } or { - Leave: { Count: > 0 } + Leave.Count: > 0 } }; @@ -278,7 +284,7 @@ public class SyncController(ILogger<SyncController> logger, TokenService tokenSe if (!hasData) { // logger.LogDebug($"Sync response has no data, stalling for 1000ms: {resp.ToJson(indent: false, ignoreNull: true)}"); - await Task.Delay(10); + // await Task.Delay(100); } return hasData; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/AccountDataController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/AccountDataController.cs
index a32d283..41cf62a 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/AccountDataController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/AccountDataController.cs
@@ -1,9 +1,5 @@ using System.Text.Json.Nodes; -using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; -using LibMatrix.Filters; using LibMatrix.HomeserverEmulator.Services; -using LibMatrix.Responses; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/FilterController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/FilterController.cs
index bdee7bc..f163a8e 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/FilterController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/FilterController.cs
@@ -1,9 +1,5 @@ -using System.Text.Json.Nodes; -using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; using LibMatrix.Filters; using LibMatrix.HomeserverEmulator.Services; -using LibMatrix.Responses; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/ProfileController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/ProfileController.cs
index 98c41da..7afdcb5 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/ProfileController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/ProfileController.cs
@@ -1,9 +1,5 @@ using System.Text.Json.Nodes; -using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; -using LibMatrix.Filters; using LibMatrix.HomeserverEmulator.Services; -using LibMatrix.Responses; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/UserController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/UserController.cs
index 2be3896..40f3667 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/UserController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Users/UserController.cs
@@ -1,10 +1,6 @@ -using System.Text.Json.Nodes; using System.Text.Json.Serialization; -using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; -using LibMatrix.Filters; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Services; -using LibMatrix.Responses; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs
index 0c3bde6..93e4b4f 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs
@@ -1,8 +1,6 @@ -using System.Text.Json.Nodes; using System.Text.Json.Serialization; using LibMatrix.Homeservers; using LibMatrix.Responses; -using LibMatrix.Services; using Microsoft.AspNetCore.Mvc; namespace LibMatrix.HomeserverEmulator.Controllers; @@ -30,6 +28,11 @@ public class VersionsController(ILogger<WellKnownController> logger) : Controlle "v1.6", "v1.7", "v1.8", + "v1.9", + "v1.10", + "v1.11", + "v1.12", + "v1.13" }, UnstableFeatures = new() }; diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs
index 97e460d..3cec712 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs
@@ -1,32 +1,34 @@ -using System.Text.Json.Nodes; -using LibMatrix.Services; -using Microsoft.AspNetCore.Mvc; - -namespace LibMatrix.HomeserverEmulator.Controllers; - -[ApiController] -[Route("/.well-known/matrix/")] -public class WellKnownController(ILogger<WellKnownController> logger) : ControllerBase { - [HttpGet("client")] - public JsonObject GetClientWellKnown() { - var obj = new JsonObject() { - ["m.homeserver"] = new JsonObject() { - ["base_url"] = $"{Request.Scheme}://{Request.Host}" - } - }; - - logger.LogInformation("Serving client well-known: {}", obj); - - return obj; - } - [HttpGet("server")] - public JsonObject GetServerWellKnown() { - var obj = new JsonObject() { - ["m.server"] = $"{Request.Scheme}://{Request.Host}" - }; - - logger.LogInformation("Serving server well-known: {}", obj); - - return obj; - } +using System.Text.Json.Nodes; +using Microsoft.AspNetCore.Mvc; + +namespace LibMatrix.HomeserverEmulator.Controllers; + +[ApiController] +[Route("/.well-known/matrix/")] +public class WellKnownController(ILogger<WellKnownController> logger) : ControllerBase { + [HttpGet("client")] + public JsonObject GetClientWellKnown() { + var obj = new JsonObject() { + ["m.homeserver"] = new JsonObject() { + // ["base_url"] = $"{Request.Scheme}://{Request.Host}" + ["base_url"] = $"https://{Request.Host}" + } + }; + + logger.LogInformation("Serving client well-known: {}", obj); + + return obj; + } + + [HttpGet("server")] + public JsonObject GetServerWellKnown() { + var obj = new JsonObject() { + // ["m.server"] = $"{Request.Scheme}://{Request.Host}" + ["m.server"] = $"https://{Request.Host}" + }; + + logger.LogInformation("Serving server well-known: {}", obj); + + return obj; + } } \ No newline at end of file diff --git a/Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj b/Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj
index f5ff2d1..5178012 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj +++ b/Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj
@@ -11,8 +11,8 @@ <ItemGroup> <PackageReference Include="EasyCompressor.LZMA" Version="2.0.2" /> - <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" /> - <PackageReference Include="Swashbuckle.AspNetCore" Version="7.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.1" /> + <PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" /> </ItemGroup> <ItemGroup> @@ -1027,6 +1027,8 @@ <_ContentIncludedByDefault Remove="data\rooms\!ffda8b8c-baf0-4938-bda5-12d30ef39fe8.json" /> <_ContentIncludedByDefault Remove="data\rooms\!ffe1fed4-8e49-4584-8f74-a1f9a58b70ed.json" /> <_ContentIncludedByDefault Remove="data\rooms\!ffffc7e7-4b1e-40a9-9f24-ebd95267e758.json" /> + <_ContentIncludedByDefault Remove="data\users\@emma:hse.localhost\tokens.json" /> + <_ContentIncludedByDefault Remove="data\users\@emma:hse.localhost\user.json" /> </ItemGroup> </Project> diff --git a/Utilities/LibMatrix.HomeserverEmulator/Program.cs b/Utilities/LibMatrix.HomeserverEmulator/Program.cs
index 9ea6fce..c72df5a 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Program.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Program.cs
@@ -1,7 +1,6 @@ using System.Net.Mime; using System.Text.Json.Serialization; using LibMatrix; -using LibMatrix.HomeserverEmulator.Extensions; using LibMatrix.HomeserverEmulator.Services; using LibMatrix.Services; using Microsoft.AspNetCore.Diagnostics; @@ -32,7 +31,7 @@ builder.Services.AddSwaggerGen(c => { }); builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); -builder.Services.AddSingleton<HSEConfiguration>(); +builder.Services.AddSingleton<HseConfiguration>(); builder.Services.AddSingleton<UserStore>(); builder.Services.AddSingleton<RoomStore>(); builder.Services.AddSingleton<MediaStore>(); @@ -77,7 +76,7 @@ app.UseExceptionHandler(exceptionHandlerApp => { var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>(); if (exceptionHandlerPathFeature?.Error is not null) - Console.WriteLine(exceptionHandlerPathFeature.Error.ToString()!); + Console.WriteLine(exceptionHandlerPathFeature.Error.ToString()); if (exceptionHandlerPathFeature?.Error is MatrixException mxe) { context.Response.StatusCode = mxe.ErrorCode switch { @@ -86,14 +85,14 @@ app.UseExceptionHandler(exceptionHandlerApp => { _ => StatusCodes.Status500InternalServerError }; context.Response.ContentType = MediaTypeNames.Application.Json; - await context.Response.WriteAsync(mxe.GetAsJson()!); + await context.Response.WriteAsync(mxe.GetAsJson()); } else { context.Response.StatusCode = StatusCodes.Status500InternalServerError; context.Response.ContentType = MediaTypeNames.Application.Json; await context.Response.WriteAsync(new MatrixException() { ErrorCode = "M_UNKNOWN", - Error = exceptionHandlerPathFeature?.Error.ToString() + Error = exceptionHandlerPathFeature?.Error?.ToString() ?? "Unknown error" }.GetAsJson()); } }); diff --git a/Utilities/LibMatrix.HomeserverEmulator/Services/HSEConfiguration.cs b/Utilities/LibMatrix.HomeserverEmulator/Services/HSEConfiguration.cs
index bcfb629..04ce050 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Services/HSEConfiguration.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Services/HSEConfiguration.cs
@@ -4,12 +4,12 @@ using ArcaneLibs.Extensions; namespace LibMatrix.HomeserverEmulator.Services; -public class HSEConfiguration { - private static ILogger<HSEConfiguration> _logger; - public static HSEConfiguration Current { get; set; } +public class HseConfiguration { + private static ILogger<HseConfiguration> _logger; + public static HseConfiguration Current { get; set; } [RequiresUnreferencedCode("Uses reflection binding")] - public HSEConfiguration(ILogger<HSEConfiguration> logger, IConfiguration config, HostBuilderContext host) { + public HseConfiguration(ILogger<HseConfiguration> logger, IConfiguration config, HostBuilderContext host) { Current = this; _logger = logger; logger.LogInformation("Loading configuration for environment: {}...", host.HostingEnvironment.EnvironmentName); @@ -22,15 +22,15 @@ public class HSEConfiguration { _logger.LogInformation("Configuration loaded: {}", this.ToJson()); } - public string CacheStoragePath { get; set; } + public required string CacheStoragePath { get; set; } - public string DataStoragePath { get; set; } + public required string DataStoragePath { get; set; } - public bool StoreData { get; set; } = true; + public required bool StoreData { get; set; } = true; - public string ServerName { get; set; } = "localhost"; + public required string ServerName { get; set; } = "localhost"; - public bool UnknownSyncTokenIsInitialSync { get; set; } = true; + public required bool UnknownSyncTokenIsInitialSync { get; set; } = true; private static string ExpandPath(string path, bool retry = true) { _logger.LogInformation("Expanding path `{}`", path); diff --git a/Utilities/LibMatrix.HomeserverEmulator/Services/MediaStore.cs b/Utilities/LibMatrix.HomeserverEmulator/Services/MediaStore.cs
index 00f2a42..7945d3a 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Services/MediaStore.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Services/MediaStore.cs
@@ -4,18 +4,18 @@ using LibMatrix.Services; namespace LibMatrix.HomeserverEmulator.Services; public class MediaStore { - private readonly HSEConfiguration _config; + private readonly HseConfiguration _config; private readonly HomeserverResolverService _hsResolver; - private List<MediaInfo> index = new(); + private List<MediaInfo> _mediaIndex = new(); - public MediaStore(HSEConfiguration config, HomeserverResolverService hsResolver) { + public MediaStore(HseConfiguration config, HomeserverResolverService hsResolver) { _config = config; _hsResolver = hsResolver; if (config.StoreData) { var path = Path.Combine(config.DataStoragePath, "media"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); if (File.Exists(Path.Combine(path, "index.json"))) - index = JsonSerializer.Deserialize<List<MediaInfo>>(File.ReadAllText(Path.Combine(path, "index.json"))); + _mediaIndex = JsonSerializer.Deserialize<List<MediaInfo>>(File.ReadAllText(Path.Combine(path, "index.json"))); } else Console.WriteLine("Data storage is disabled, not loading rooms from disk"); @@ -36,7 +36,9 @@ public class MediaStore { if (_config.StoreData) { var path = Path.Combine(_config.DataStoragePath, "media", serverName, mediaId); if (!File.Exists(path)) { - var mediaUrl = await _hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + // var mediaUrl = await _hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + var homeserver = (await _hsResolver.ResolveHomeserverFromWellKnown(serverName)).Client; + var mediaUrl = homeserver is null ? null : $"{homeserver}/_matrix/media/v3/download/"; if (mediaUrl is null) throw new MatrixException() { ErrorCode = "M_NOT_FOUND", @@ -50,7 +52,9 @@ public class MediaStore { return new FileStream(path, FileMode.Open); } else { - var mediaUrl = await _hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + // var mediaUrl = await _hsResolver.ResolveMediaUri(serverName, $"mxc://{serverName}/{mediaId}"); + var homeserver = (await _hsResolver.ResolveHomeserverFromWellKnown(serverName)).Client; + var mediaUrl = homeserver is null ? null : $"{homeserver}/_matrix/media/v3/download/"; if (mediaUrl is null) throw new MatrixException() { ErrorCode = "M_NOT_FOUND", diff --git a/Utilities/LibMatrix.HomeserverEmulator/Services/PaginationTokenResolverService.cs b/Utilities/LibMatrix.HomeserverEmulator/Services/PaginationTokenResolverService.cs
index 0128ba6..0603a2d 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Services/PaginationTokenResolverService.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Services/PaginationTokenResolverService.cs
@@ -35,15 +35,15 @@ public class PaginationTokenResolverService(ILogger<PaginationTokenResolverServi } } - public async Task<StateEventResponse?> ResolveTokenToEvent(string token, RoomStore.Room room) { + public Task<StateEventResponse?> ResolveTokenToEvent(string token, RoomStore.Room room) { if (token.StartsWith('$')) { //we have an event ID logger.LogTrace("ResolveTokenToEvent(EventId({token}), Room({room})): searching for event...", token, room.RoomId); var evt = room.Timeline.SingleOrDefault(x => x.EventId == token); - if (evt is not null) return evt; + if (evt is not null) return Task.FromResult(evt); logger.LogTrace("ResolveTokenToEvent({token}, Room({room})): event not in requested room...", token, room.RoomId); - return null; + return Task.FromResult<StateEventResponse?>(null); } else { // we have a sync token diff --git a/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs b/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs
index c798cce..b6fe7c2 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs
@@ -2,13 +2,12 @@ using System.Collections.Concurrent; using System.Collections.Frozen; using System.Collections.Immutable; using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.Text.Json; using System.Text.Json.Nodes; using ArcaneLibs; using ArcaneLibs.Collections; using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.HomeserverEmulator.Controllers.Rooms; using LibMatrix.Responses; @@ -19,14 +18,14 @@ public class RoomStore { public ConcurrentBag<Room> _rooms = new(); private FrozenDictionary<string, Room> _roomsById = FrozenDictionary<string, Room>.Empty; - public RoomStore(ILogger<RoomStore> logger, HSEConfiguration config) { + public RoomStore(ILogger<RoomStore> logger, HseConfiguration config) { _logger = logger; if (config.StoreData) { var path = Path.Combine(config.DataStoragePath, "rooms"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); foreach (var file in Directory.GetFiles(path)) { var room = JsonSerializer.Deserialize<Room>(File.ReadAllText(file)); - if (room is not null) _rooms.Add(room); + if (room is not null && room.State.Any(x => x.Type == RoomCreateEventContent.EventId)) _rooms.Add(room); } } else @@ -35,25 +34,8 @@ public class RoomStore { RebuildIndexes(); } - private SemaphoreSlim a = new(1, 1); private void RebuildIndexes() { - // a.Wait(); - // lock (_roomsById) - // _roomsById = new ConcurrentDictionary<string, Room>(_rooms.ToDictionary(u => u.RoomId)); - // foreach (var room in _rooms) { - // _roomsById.AddOrUpdate(room.RoomId, room, (key, old) => room); - // } - // - // var roomsArr = _rooms.ToArray(); - // foreach (var (id, room) in _roomsById) { - // if (!roomsArr.Any(x => x.RoomId == id)) - // _roomsById.TryRemove(id, out _); - // } - - // _roomsById = new ConcurrentDictionary<string, Room>(_rooms.ToDictionary(u => u.RoomId)); _roomsById = _rooms.ToFrozenDictionary(u => u.RoomId); - - // a.Release(); } public Room? GetRoomById(string roomId, bool createIfNotExists = false) { @@ -64,18 +46,19 @@ public class RoomStore { if (!createIfNotExists) return null; - return CreateRoom(new() { }); + return CreateRoom(new()); } public Room CreateRoom(CreateRoomRequest request, UserStore.User? user = null) { var room = new Room(roomId: $"!{Guid.NewGuid().ToString()}"); var newCreateEvent = new StateEvent() { Type = RoomCreateEventContent.EventId, - RawContent = new() { } + RawContent = new() }; foreach (var (key, value) in request.CreationContent) { newCreateEvent.RawContent[key] = value.DeepClone(); + Console.WriteLine($"RawContent[{key}] = {value.DeepClone().ToJson(ignoreNull: true)}"); } if (user != null) { @@ -207,7 +190,7 @@ public class RoomStore { : JsonSerializer.Deserialize<JsonObject>(JsonSerializer.Serialize(request.TypedContent))) }; Timeline.Add(state); - if(state.StateKey != null) + if (state.StateKey != null) RebuildState(); return state; } @@ -226,32 +209,36 @@ public class RoomStore { } // public async Task SaveDebounced() { - // if (!HSEConfiguration.Current.StoreData) return; - // await _debounceCts.CancelAsync(); - // _debounceCts = new CancellationTokenSource(); - // try { - // await Task.Delay(250, _debounceCts.Token); - // // Ensure all state events are in the timeline - // State.Where(s => !Timeline.Contains(s)).ToList().ForEach(s => Timeline.Add(s)); - // var path = Path.Combine(HSEConfiguration.Current.DataStoragePath, "rooms", $"{RoomId}.json"); - // Console.WriteLine($"Saving room {RoomId} to {path}!"); - // await File.WriteAllTextAsync(path, this.ToJson(ignoreNull: true)); - // } - // catch (TaskCanceledException) { } + // if (!HSEConfiguration.Current.StoreData) return; + // await _debounceCts.CancelAsync(); + // _debounceCts = new CancellationTokenSource(); + // try { + // await Task.Delay(250, _debounceCts.Token); + // // Ensure all state events are in the timeline + // State.Where(s => !Timeline.Contains(s)).ToList().ForEach(s => Timeline.Add(s)); + // var path = Path.Combine(HSEConfiguration.Current.DataStoragePath, "rooms", $"{RoomId}.json"); + // Console.WriteLine($"Saving room {RoomId} to {path}!"); + // await File.WriteAllTextAsync(path, this.ToJson(ignoreNull: true)); + // } + // catch (TaskCanceledException) { } // } private SemaphoreSlim saveSemaphore = new(1, 1); + private CancellationTokenSource _saveCts = new(); + public async Task SaveDebounced() { Task.Run(async () => { - await saveSemaphore.WaitAsync(); + // await saveSemaphore.WaitAsync(); + await _saveCts.CancelAsync(); + _saveCts = new(); try { - var path = Path.Combine(HSEConfiguration.Current.DataStoragePath, "rooms", $"{RoomId}.json"); - Console.WriteLine($"Saving room {RoomId} to {path}!"); - await File.WriteAllTextAsync(path, this.ToJson(ignoreNull: true)); + var path = Path.Combine(HseConfiguration.Current.DataStoragePath, "rooms", $"{RoomId}.json"); + // Console.WriteLine($"Saving room {RoomId} to {path}!"); + await File.WriteAllTextAsync(path, this.ToJson(ignoreNull: true), _saveCts.Token); } finally { - saveSemaphore.Release(); + // saveSemaphore.Release(); } }); } diff --git a/Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs b/Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs
index 4684b01..7f211e3 100644 --- a/Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs +++ b/Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs
@@ -5,7 +5,6 @@ using System.Text.Json.Nodes; using ArcaneLibs; using ArcaneLibs.Collections; using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec.State; using LibMatrix.Filters; using LibMatrix.Responses; @@ -13,14 +12,14 @@ namespace LibMatrix.HomeserverEmulator.Services; public class UserStore { public ConcurrentBag<User> _users = new(); - private readonly HSEConfiguration _config; + private readonly HseConfiguration _config; private readonly RoomStore _roomStore; - public UserStore(HSEConfiguration config, RoomStore roomStore) { + public UserStore(HseConfiguration config, RoomStore roomStore) { _config = config; _roomStore = roomStore; if (config.StoreData) { - var dataDir = Path.Combine(HSEConfiguration.Current.DataStoragePath, "users"); + var dataDir = Path.Combine(HseConfiguration.Current.DataStoragePath, "users"); if (!Directory.Exists(dataDir)) Directory.CreateDirectory(dataDir); foreach (var userId in Directory.GetDirectories(dataDir)) { var tokensDir = Path.Combine(dataDir, userId, "tokens.json"); @@ -138,7 +137,7 @@ public class UserStore { private ObservableDictionary<string, object> _profile; private ObservableCollection<StateEventResponse> _accountData; private ObservableDictionary<string, RoomKeysResponse> _roomKeys; - private ObservableDictionary<string, AuthorizedSession> _authorizedSessions; + private ObservableDictionary<string, LoginResponse> _authorizedSessions; public string UserId { get => _userId; @@ -195,7 +194,7 @@ public class UserStore { } } - public ObservableDictionary<string, AuthorizedSession> AuthorizedSessions { + public ObservableDictionary<string, LoginResponse> AuthorizedSessions { get => _authorizedSessions; set { if (value == _authorizedSessions) return; @@ -208,12 +207,12 @@ public class UserStore { public bool IsGuest { get; set; } public async Task SaveDebounced() { - if (!HSEConfiguration.Current.StoreData) return; + if (!HseConfiguration.Current.StoreData) return; await _debounceCts.CancelAsync(); _debounceCts = new CancellationTokenSource(); try { await Task.Delay(250, _debounceCts.Token); - var dataDir = Path.Combine(HSEConfiguration.Current.DataStoragePath, "users", _userId); + var dataDir = Path.Combine(HseConfiguration.Current.DataStoragePath, "users", _userId); if (!Directory.Exists(dataDir)) Directory.CreateDirectory(dataDir); var tokensDir = Path.Combine(dataDir, "tokens.json"); var path = Path.Combine(dataDir, $"user.json"); @@ -264,10 +263,5 @@ public class UserStore { UserId = UserId }; } - - public class AuthorizedSession { - public string Homeserver { get; set; } - public string AccessToken { get; set; } - } } } \ No newline at end of file diff --git a/Utilities/LibMatrix.TestDataGenerator/LibMatrix.TestDataGenerator.csproj b/Utilities/LibMatrix.TestDataGenerator/LibMatrix.TestDataGenerator.csproj
index 879693e..b054aba 100644 --- a/Utilities/LibMatrix.TestDataGenerator/LibMatrix.TestDataGenerator.csproj +++ b/Utilities/LibMatrix.TestDataGenerator/LibMatrix.TestDataGenerator.csproj
@@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFramework>net8.0</TargetFramework> + <TargetFramework>net9.0</TargetFramework> <LangVersion>preview</LangVersion> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> @@ -17,7 +17,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/> + <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1"/> </ItemGroup> <ItemGroup> <Content Include="appsettings*.json"> @@ -27,6 +27,6 @@ <ItemGroup> <ProjectReference Include="..\..\LibMatrix\LibMatrix.csproj"/> <ProjectReference Include="..\..\Utilities\LibMatrix.Utilities.Bot\LibMatrix.Utilities.Bot.csproj"/> - <ProjectReference Include="..\LibMatrix.Tests\LibMatrix.Tests.csproj"/> + <ProjectReference Include="..\..\Tests\LibMatrix.Tests\LibMatrix.Tests.csproj"/> </ItemGroup> </Project> diff --git a/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs b/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs
index 2cfcf32..6dc76f6 100644 --- a/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs +++ b/Utilities/LibMatrix.Utilities.Bot/AppServices/AppServiceConfiguration.cs
@@ -4,28 +4,28 @@ namespace LibMatrix.Utilities.Bot.AppServices; public class AppServiceConfiguration { [JsonPropertyName("id")] - public string Id { get; set; } = null!; + public string Id { get; set; } [JsonPropertyName("url")] - public string? Url { get; set; } = null!; + public string? Url { get; set; } [JsonPropertyName("sender_localpart")] - public string SenderLocalpart { get; set; } = null!; + public string SenderLocalpart { get; set; } [JsonPropertyName("as_token")] - public string AppserviceToken { get; set; } = null!; + public string AppserviceToken { get; set; } [JsonPropertyName("hs_token")] - public string HomeserverToken { get; set; } = null!; + public string HomeserverToken { get; set; } [JsonPropertyName("protocols")] - public List<string>? Protocols { get; set; } = null!; + public List<string>? Protocols { get; set; } [JsonPropertyName("rate_limited")] - public bool? RateLimited { get; set; } = null!; + public bool? RateLimited { get; set; } [JsonPropertyName("namespaces")] - public AppserviceNamespaces Namespaces { get; set; } = null!; + public AppserviceNamespaces Namespaces { get; set; } public class AppserviceNamespaces { [JsonPropertyName("users")] @@ -42,7 +42,7 @@ public class AppServiceConfiguration { public bool Exclusive { get; set; } [JsonPropertyName("regex")] - public string Regex { get; set; } = null!; + public string Regex { get; set; } } } diff --git a/Utilities/LibMatrix.Utilities.Bot/Commands/AliassesCommand.cs b/Utilities/LibMatrix.Utilities.Bot/Commands/AliassesCommand.cs
index 5c9c480..9107c4c 100644 --- a/Utilities/LibMatrix.Utilities.Bot/Commands/AliassesCommand.cs +++ b/Utilities/LibMatrix.Utilities.Bot/Commands/AliassesCommand.cs
@@ -1,4 +1,3 @@ -using System.Collections.Frozen; using System.Text; using LibMatrix.EventTypes.Spec; using LibMatrix.Helpers; diff --git a/Utilities/LibMatrix.Utilities.Bot/Commands/HelpCommand.cs b/Utilities/LibMatrix.Utilities.Bot/Commands/HelpCommand.cs
index 0abc76b..d55c67c 100644 --- a/Utilities/LibMatrix.Utilities.Bot/Commands/HelpCommand.cs +++ b/Utilities/LibMatrix.Utilities.Bot/Commands/HelpCommand.cs
@@ -1,6 +1,3 @@ -using System.Collections.Frozen; -using System.Text; -using LibMatrix.EventTypes.Spec; using LibMatrix.Helpers; using LibMatrix.Utilities.Bot.Interfaces; using Microsoft.Extensions.DependencyInjection; diff --git a/Utilities/LibMatrix.Utilities.Bot/Interfaces/ICommand.cs b/Utilities/LibMatrix.Utilities.Bot/Interfaces/ICommand.cs
index 941d69e..7b4afa9 100644 --- a/Utilities/LibMatrix.Utilities.Bot/Interfaces/ICommand.cs +++ b/Utilities/LibMatrix.Utilities.Bot/Interfaces/ICommand.cs
@@ -1,7 +1,3 @@ -using System.Collections.Frozen; -using System.Collections.Immutable; -using Microsoft.Extensions.DependencyInjection; - namespace LibMatrix.Utilities.Bot.Interfaces; public interface ICommand { diff --git a/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj b/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj
index 0d0c2ae..bbb0a65 100644 --- a/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj +++ b/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj
@@ -12,9 +12,9 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> - <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" /> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.1" /> + <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.1" /> </ItemGroup> diff --git a/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs b/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs
index 728b169..da83cfa 100644 --- a/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs +++ b/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs
@@ -1,4 +1,3 @@ -using LibMatrix.Utilities.Bot.Interfaces; using Microsoft.Extensions.Configuration; namespace LibMatrix.Utilities.Bot; diff --git a/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs b/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
index 9a7585e..d07090f 100644 --- a/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs +++ b/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
@@ -1,7 +1,6 @@ -using System.Reflection.Metadata; using ArcaneLibs.Extensions; using LibMatrix.EventTypes.Spec; -using LibMatrix.EventTypes.Spec.State; +using LibMatrix.EventTypes.Spec.State.RoomInfo; using LibMatrix.Filters; using LibMatrix.Helpers; using LibMatrix.Homeservers; diff --git a/Utilities/LibMatrix.Utilities.Bot/Services/InviteListenerHostedService.cs b/Utilities/LibMatrix.Utilities.Bot/Services/InviteListenerHostedService.cs
index 7c5cc44..88a6a03 100644 --- a/Utilities/LibMatrix.Utilities.Bot/Services/InviteListenerHostedService.cs +++ b/Utilities/LibMatrix.Utilities.Bot/Services/InviteListenerHostedService.cs
@@ -1,12 +1,6 @@ -using System.Reflection.Metadata; -using ArcaneLibs.Extensions; -using LibMatrix.EventTypes.Spec; using LibMatrix.Filters; using LibMatrix.Helpers; using LibMatrix.Homeservers; -using LibMatrix.Responses; -using LibMatrix.Utilities.Bot.Interfaces; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging;