diff --git a/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs
index 4f10601..d0eaed4 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/AuthController.cs
@@ -12,13 +12,10 @@ public class AuthController(ILogger<AuthController> logger, UserStore userStore,
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 2e232d9..d497ca6 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/DirectoryController.cs
@@ -1,3 +1,4 @@
+using System.Text.Json.Serialization;
using ArcaneLibs.Extensions;
using LibMatrix.EventTypes.Spec.State.RoomInfo;
using LibMatrix.HomeserverEmulator.Services;
@@ -32,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
@@ -61,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/Rooms/RoomTimelineController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
index b6ec6bf..61195b8 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
@@ -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/SyncController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs
index cfab3a6..86c9f6a 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/SyncController.cs
@@ -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/VersionsController.cs b/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs
index 9b8ce62..93e4b4f 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/VersionsController.cs
@@ -28,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 bae4c74..3cec712 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Controllers/WellKnownController.cs
@@ -1,31 +1,34 @@
-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}"
- }
- };
-
- 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 2218fb2..5178012 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj
+++ b/Utilities/LibMatrix.HomeserverEmulator/LibMatrix.HomeserverEmulator.csproj
@@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<LangVersion>preview</LangVersion>
-<!-- <GenerateDocumentationFile>true</GenerateDocumentationFile>-->
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<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/Services/RoomStore.cs b/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs
index 2f5fa32..c15fe7d 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Services/RoomStore.cs
@@ -25,7 +25,7 @@ public class RoomStore {
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
@@ -33,7 +33,7 @@ public class RoomStore {
RebuildIndexes();
}
-
+
private void RebuildIndexes() {
_roomsById = _rooms.ToFrozenDictionary(u => u.RoomId);
}
@@ -58,6 +58,7 @@ public class RoomStore {
foreach (var (key, value) in request.CreationContent) {
newCreateEvent.RawContent[key] = value.DeepClone();
+ Console.WriteLine($"RawContent[{key}] = {value.DeepClone().ToJson(ignoreNull: true)}");
}
if (user != null) {
@@ -189,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;
}
@@ -208,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));
+ // 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 d1b0a30..7f211e3 100644
--- a/Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs
+++ b/Utilities/LibMatrix.HomeserverEmulator/Services/UserStore.cs
@@ -137,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;
@@ -194,7 +194,7 @@ public class UserStore {
}
}
- public ObservableDictionary<string, AuthorizedSession> AuthorizedSessions {
+ public ObservableDictionary<string, LoginResponse> AuthorizedSessions {
get => _authorizedSessions;
set {
if (value == _authorizedSessions) return;
@@ -263,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
|