about summary refs log tree commit diff
path: root/MiniUtils/Commands/DetectStateSplitCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MiniUtils/Commands/DetectStateSplitCommand.cs')
-rw-r--r--MiniUtils/Commands/DetectStateSplitCommand.cs72
1 files changed, 72 insertions, 0 deletions
diff --git a/MiniUtils/Commands/DetectStateSplitCommand.cs b/MiniUtils/Commands/DetectStateSplitCommand.cs
new file mode 100644

index 0000000..6180f20 --- /dev/null +++ b/MiniUtils/Commands/DetectStateSplitCommand.cs
@@ -0,0 +1,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()); + } +} \ No newline at end of file