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()); } }