about summary refs log tree commit diff
path: root/Tests/LibMatrix.HomeserverEmulator/Controllers/LegacyController.cs
blob: 1fb427ea7b824a9e67bdc8d8c3663c7a5992cf33 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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.HomeserverEmulator.Services;
using LibMatrix.Responses;
using LibMatrix.Services;
using Microsoft.AspNetCore.Mvc;

namespace LibMatrix.HomeserverEmulator.Controllers;

[ApiController]
[Route("/_matrix/client/{version}/")]
public class LegacyController(ILogger<LegacyController> logger, TokenService tokenService, UserStore userStore, RoomStore roomStore) : ControllerBase {
    [HttpGet("rooms/{roomId}/initialSync")]
    [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<object> Sync([FromRoute] string roomId, [FromQuery] int limit = 20) {
        var sw = Stopwatch.StartNew();
        var token = tokenService.GetAccessTokenOrNull(HttpContext);
        if (token == null)
            throw new MatrixException() {
                ErrorCode = "M_MISSING_TOKEN",
                Error = "Missing token"
            };

        var user = await userStore.GetUserByToken(token);
        if (user == null)
            throw new MatrixException() {
                ErrorCode = "M_UNKNOWN_TOKEN",
                Error = "No such user"
            };
        var room = roomStore.GetRoomById(roomId);
        if (room is null)
            throw new MatrixException() {
                ErrorCode = "M_NOT_FOUND",
                Error = "Room not found."
            };
        var accountData = room.AccountData.GetOrCreate(user.UserId, _ => []);
        var membership = room.State.FirstOrDefault(x => x.Type == "m.room.member" && x.StateKey == user.UserId);
        var timelineChunk = room.Timeline.TakeLast(limit).ToList();
        return new {
            account_data = accountData,
            membership = (membership?.TypedContent as RoomMemberEventContent)?.Membership ?? "leave",
            room_id = room.RoomId,
            state = room.State.ToList(),
            visibility = "public",
            messages = new PaginatedChunkedStateEventResponse() {
                Chunk = timelineChunk,
                End = timelineChunk.Last().EventId,
                Start = timelineChunk.Count >= limit ? timelineChunk.First().EventId : null
            }
        };
    }
}