about summary refs log tree commit diff
path: root/MiniUtils/Commands/DetectStateSplitCommand.cs
blob: 6180f20fa7ef1d89ed6e6c88a81079350b07f8bf (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
using System.Collections.Frozen;
using ArcaneLibs.Extensions;
using LibMatrix;
using LibMatrix.Helpers;
using LibMatrix.Services;
using LibMatrix.Utilities.Bot.Interfaces;

namespace MiniUtils.Commands;

public class DetectStateSplitCommand(MiniUtilsConfiguration config, HomeserverProviderService hsProvider) : ICommand {
    public string Name => "detect state split";

    public string[]? Aliases => ["dss"];

    public string Description => "Detect room splits";

    public bool Unlisted => false;

    public async Task Invoke(CommandContext ctx) {
        var profile = config.ExternalProfiles[ctx.Args[0]];
        var rhs = await hsProvider.GetAuthenticatedWithToken(profile.Homeserver, profile.AccessToken, enableServer: false, useGeneric: true);
        var localStateTask = ctx.Room.GetFullStateAsListAsync();
        var remoteStateTask = rhs.GetRoom(ctx.Room.RoomId).GetFullStateAsListAsync();

        var localState = await localStateTask;
        var remoteState = await remoteStateTask;

        var keySet = localState.Concat(remoteState)
            .Select(x => (x.Type, x.StateKey))
            .ToFrozenSet();

        var differences = 0;
        foreach (var keyPair in keySet) {
            var local = localState.FirstOrDefault(x => x.Type == keyPair.Type && x.StateKey == keyPair.StateKey);
            var remote = remoteState.FirstOrDefault(x => x.Type == keyPair.Type && x.StateKey == keyPair.StateKey);
            
            if (local == null) {
                await ctx.Room.SendMessageEventAsync(new MessageBuilder()
                    .WithCollapsibleSection($"Missing {keyPair.Type} {keyPair.StateKey} locally", b =>
                        b.WithCodeBlock(remote.ToJson(ignoreNull: true), "json")
                    ).Build());
                differences++;
                continue;
            }

            if (remote == null) {
                await ctx.Room.SendMessageEventAsync(new MessageBuilder()
                    .WithCollapsibleSection($"Missing {keyPair.Type} {keyPair.StateKey} remotely", b =>
                        b.WithCodeBlock(local.ToJson(ignoreNull: true), "json")
                    ).Build());
                differences++;
                continue;
            }

            if (!StateEvent.Equals(local, remote)) {
                await ctx.Room.SendMessageEventAsync(new MessageBuilder()
                    .WithCollapsibleSection($"Different {keyPair.Type} {keyPair.StateKey}", b =>
                        b.WithCodeBlock(local.ToJson(ignoreNull: true), "json")
                            .WithCodeBlock(remote.ToJson(ignoreNull: true), "json")
                    ).Build());
                differences++;
            }
        }

        if (differences > 0)
            await ctx.Room.SendMessageEventAsync(new MessageBuilder().WithBody($"No differences found").Build());
        else
            await ctx.Room.SendMessageEventAsync(new MessageBuilder().WithBody($"Found {differences} differences!").Build());

        // await ctx.Room.SendMessageEventAsync(new MessageBuilder().WithCodeBlock(rhs.WhoAmI.ToJson()).Build());
    }
}