summary refs log tree commit diff
path: root/ModAS.Server/Controllers/AppService/TransactionsController.cs
blob: b74e1e17f06e354b5595fdda889cd75e2162b5f4 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System.IO.Pipelines;
using System.Net;
using System.Net.Http.Headers;
using System.Text.Json;
using ArcaneLibs;
using LibMatrix;
using LibMatrix.EventTypes.Spec;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration.Json;
using ModAS.Server;
using ModAS.Server.Services;
using MxApiExtensions.Services;

namespace ModAS.Server.Controllers.AppService;

[ApiController]
public class TransactionsController(
    AppServiceRegistration asr,
    ModASConfiguration config,
    UserProviderService userProvider,
    RoomContextService roomContextService,
    RoomStateCacheService stateCacheService) : ControllerBase {
    private static List<string> _ignoredInvalidationEvents { get; set; } = [
        RoomMessageEventContent.EventId,
        RoomMessageReactionEventContent.EventId
    ];

    [HttpPut("/_matrix/app/v1/transactions/{txnId}")]
    public async Task<IActionResult> PutTransactions(string txnId) {
        if (!Request.Headers.ContainsKey("Authorization")) {
            Console.WriteLine("PutTransaction: missing authorization header");
            return Unauthorized();
        }

        if (Request.GetTypedHeaders().Get<AuthenticationHeaderValue>("Authorization")?.Parameter != asr.HomeserverToken) {
            Console.WriteLine($"PutTransaction: invalid authorization header: {Request.Headers["Authorization"]}");
            return Unauthorized();
        }

        var data = await JsonSerializer.DeserializeAsync<EventList>(Request.Body);
        Console.WriteLine(
            $"PutTransaction: {txnId}: {data.Events.Count} events, {Util.BytesToString(Request.Headers.ContentLength ?? Request.ContentLength ?? Request.Body.Length)}");

        if (!Directory.Exists("data"))
            Directory.CreateDirectory("data");
        Directory.CreateDirectory($"data/{txnId}");
        // var pipe = PipeReader.Create(Request.Body);
        // await using var file = System.IO.File.OpenWrite($"data/{txnId}");
        // await pipe.CopyToAsync(file);
        // await pipe.CompleteAsync();
        //
        // Console.WriteLine($"PutTransaction: {txnId}: {Util.BytesToString(file.Length)}");
        for (var i = 0; i < data.Events.Count; i++) {
            var evt = data.Events[i];
            Console.WriteLine($"PutTransaction: {txnId}/{i}: {evt.Type} {evt.StateKey} {evt.Sender}");
            await System.IO.File.WriteAllTextAsync($"data/{txnId}/{i}-{evt.Type}-{evt.StateKey}-{evt.Sender}.json", JsonSerializer.Serialize(evt));

            if (evt.Sender.EndsWith(':' + config.ServerName)) {
                Console.WriteLine("PutTransaction: sender is local user, updating data...");
                try {
                    var user = await userProvider.GetImpersonatedHomeserver(evt.Sender);
                    var rooms = await user.GetJoinedRooms();
                    foreach (var room in rooms) {
                        await roomContextService.GetRoomContext(room);
                    }
                }
                catch (Exception e) {
                    Console.WriteLine($"PutTransaction: failed to update data: {e}");
                }
            }
            else
                Console.WriteLine("PutTransaction: sender is remote user");

            if (!string.IsNullOrWhiteSpace(evt.RoomId) && !_ignoredInvalidationEvents.Contains(evt.Type))
                await stateCacheService.InvalidateRoomState(evt.RoomId);
        }

        return Ok(new { });
    }
}