about summary refs log tree commit diff
path: root/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms')
-rw-r--r--Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomStateController.cs7
-rw-r--r--Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs116
-rw-r--r--Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs59
3 files changed, 138 insertions, 44 deletions
diff --git a/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomStateController.cs b/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomStateController.cs
index 3896ac0..a1738c9 100644
--- a/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomStateController.cs
+++ b/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomStateController.cs
@@ -1,4 +1,5 @@
 using System.Collections.Frozen;
+using System.Text.Json.Nodes;
 using LibMatrix.HomeserverEmulator.Extensions;
 using LibMatrix.HomeserverEmulator.Services;
 using Microsoft.AspNetCore.Mvc;
@@ -73,12 +74,12 @@ public class RoomStateController(ILogger<RoomStateController> logger, TokenServi
     }
 
     [HttpPut("{eventType}")]
-    public async Task<EventIdResponse> SetState(string roomId, string eventType, [FromBody] StateEvent request) {
+    public async Task<EventIdResponse> SetState(string roomId, string eventType, [FromBody] JsonObject? request) {
         return await SetState(roomId, eventType, "", request);
     }
 
     [HttpPut("{eventType}/{stateKey}")]
-    public async Task<EventIdResponse> SetState(string roomId, string eventType, string stateKey, [FromBody] StateEvent request) {
+    public async Task<EventIdResponse> SetState(string roomId, string eventType, string stateKey, [FromBody] JsonObject? request) {
         var token = tokenService.GetAccessTokenOrNull(HttpContext);
         if (token == null)
             throw new MatrixException() {
@@ -99,7 +100,7 @@ public class RoomStateController(ILogger<RoomStateController> logger, TokenServi
                 ErrorCode = "M_NOT_FOUND",
                 Error = "Room not found"
             };
-        var evt = room.SetStateInternal(request.ToStateEvent(user, room));
+        var evt = room.SetStateInternal(new StateEvent() { Type = eventType, StateKey = stateKey, RawContent = request }.ToStateEvent(user, room));
         evt.Type = eventType;
         evt.StateKey = stateKey;
         return new EventIdResponse() {
diff --git a/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs b/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
index 3d23660..afd69d1 100644
--- a/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
+++ b/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomTimelineController.cs
@@ -124,6 +124,122 @@ public class RoomTimelineController(
 
         return evt;
     }
+    
+    [HttpGet("relations/{eventId}")]
+    public async Task<RecursedBatchedChunkedStateEventResponse> GetRelations(string roomId, string eventId, [FromQuery] string? dir = "b", [FromQuery] string? from = null, [FromQuery] int? limit = 100, [FromQuery] bool? recurse = false, [FromQuery] string? to = null) {
+        var token = tokenService.GetAccessToken(HttpContext);
+        var user = await userStore.GetUserByToken(token);
+
+        var room = roomStore.GetRoomById(roomId);
+        if (room == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                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 = room.Timeline.SingleOrDefault(x => x.EventId == eventId);
+        if (evt == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                Error = "Event not found"
+            };
+
+        var matchingEvents = await GetRelationsInternal(roomId, eventId, dir, from, limit, recurse, to);
+
+        return new() {
+            Chunk = matchingEvents.ToList()
+        };
+    }
+    
+    [HttpGet("relations/{eventId}/{relationType}")]
+    public async Task<RecursedBatchedChunkedStateEventResponse> GetRelations(string roomId, string eventId, string relationType, [FromQuery] string? dir = "b", [FromQuery] string? from = null, [FromQuery] int? limit = 100, [FromQuery] bool? recurse = false, [FromQuery] string? to = null) {
+        var token = tokenService.GetAccessToken(HttpContext);
+        var user = await userStore.GetUserByToken(token);
+
+        var room = roomStore.GetRoomById(roomId);
+        if (room == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                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 = room.Timeline.SingleOrDefault(x => x.EventId == eventId);
+        if (evt == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                Error = "Event not found"
+            };
+
+        var matchingEvents = await GetRelationsInternal(roomId, eventId, dir, from, limit, recurse, to);
+
+        return new() {
+            Chunk = matchingEvents.ToList()
+        };
+    }
+    
+    [HttpGet("relations/{eventId}/{relationType}/{eventType}")]
+    public async Task<RecursedBatchedChunkedStateEventResponse> GetRelations(string roomId, string eventId, string relationType, string eventType, [FromQuery] string? dir = "b", [FromQuery] string? from = null, [FromQuery] int? limit = 100, [FromQuery] bool? recurse = false, [FromQuery] string? to = null) {
+        var token = tokenService.GetAccessToken(HttpContext);
+        var user = await userStore.GetUserByToken(token);
+
+        var room = roomStore.GetRoomById(roomId);
+        if (room == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                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 = room.Timeline.SingleOrDefault(x => x.EventId == eventId);
+        if (evt == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                Error = "Event not found"
+            };
+
+        var matchingEvents = await GetRelationsInternal(roomId, eventId, dir, from, limit, recurse, to);
+
+        return new() {
+            Chunk = matchingEvents.ToList()
+        };
+    }
+    
+    private async Task<IEnumerable<StateEventResponse>> GetRelationsInternal(string roomId, string eventId, string dir, string? from, int? limit, bool? recurse, string? to) {
+        var room = roomStore.GetRoomById(roomId);
+        var evt = room.Timeline.SingleOrDefault(x => x.EventId == eventId);
+        if (evt == null)
+            throw new MatrixException() {
+                ErrorCode = "M_NOT_FOUND",
+                Error = "Event not found"
+            };
+
+        var relatedEvents = room.Timeline.Where(x => x.RawContent?["m.relates_to"]?["event_id"]?.GetValue<string>() == eventId);
+        if (dir == "b") {
+            relatedEvents = relatedEvents.TakeLast(limit ?? 100);
+        }
+        else if (dir == "f") {
+            relatedEvents = relatedEvents.Take(limit ?? 100);
+        }
+        
+        return relatedEvents;
+    }
 
 #region Commands
 
diff --git a/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs b/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs
index 6849ff8..c24e6e9 100644
--- a/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs
+++ b/Tests/LibMatrix.HomeserverEmulator/Controllers/Rooms/RoomsController.cs
@@ -28,42 +28,9 @@ public class RoomsController(ILogger<RoomsController> logger, TokenService token
                 Error = "No such user"
             };
 
-        var room = new RoomStore.Room($"!{Guid.NewGuid()}:{tokenService.GenerateServerName(HttpContext)}");
-        var createEvent = room.SetStateInternal(new() {
-            Type = RoomCreateEventContent.EventId,
-            RawContent = new() {
-                ["creator"] = user.UserId
-            }
-        });
-        foreach (var (key, value) in request.CreationContent) {
-            createEvent.RawContent[key] = value.DeepClone();
-        }
-
-        if (!string.IsNullOrWhiteSpace(request.Name))
-            room.SetStateInternal(new StateEvent() {
-                Type = RoomNameEventContent.EventId,
-                TypedContent = new RoomNameEventContent() {
-                    Name = request.Name
-                }
-            });
-
-        if (!string.IsNullOrWhiteSpace(request.RoomAliasName))
-            room.SetStateInternal(new StateEvent() {
-                Type = RoomCanonicalAliasEventContent.EventId,
-                TypedContent = new RoomCanonicalAliasEventContent() {
-                    Alias = $"#{request.RoomAliasName}:localhost"
-                }
-            });
-
-        if (request.InitialState is { Count: > 0 }) {
-            foreach (var stateEvent in request.InitialState) {
-                room.SetStateInternal(stateEvent);
-            }
-        }
+        // var room = new RoomStore.Room($"!{Guid.NewGuid()}:{tokenService.GenerateServerName(HttpContext)}");
+        var room = roomStore.CreateRoom(request, user);
 
-        room.AddUser(user.UserId);
-
-        // user.Rooms.Add(room.RoomId, room);
         return new() {
             RoomId = room.RoomId
         };
@@ -122,9 +89,13 @@ public class RoomsController(ILogger<RoomsController> logger, TokenService token
             replacement_room = room.RoomId
         };
     }
-    
+
+    public class ReasonBody {
+        [JsonPropertyName("reason")]
+        public string? Reason { get; set; }
+    }
     [HttpPost("rooms/{roomId}/leave")] // TODO: implement
-    public async Task<object> LeaveRoom(string roomId) {
+    public async Task<object> LeaveRoom(string roomId, [FromBody] ReasonBody body) {
         var token = tokenService.GetAccessTokenOrNull(HttpContext);
         if (token == null)
             throw new MatrixException() {
@@ -145,11 +116,17 @@ public class RoomsController(ILogger<RoomsController> logger, TokenService token
                 ErrorCode = "M_NOT_FOUND",
                 Error = "Room not found"
             };
+        
+        room.SetStateInternal(new() {
+            Type = RoomMemberEventContent.EventId,
+            TypedContent = new RoomMemberEventContent() {
+                Membership = "leave",
+                Reason = body.Reason
+            },
+            StateKey = user.UserId
+        });
 
-        // room.RemoveUser(user.UserId);
-
-        // room.SetStateInternal(new StateEventResponse() { });
-
+        logger.LogTrace($"User {user.UserId} left room {room.RoomId}");
         return new {
             room_id = room.RoomId
         };