@using LibMatrix.Homeservers @using LibMatrix.RoomTypes @using LibMatrix @using LibMatrix.EventTypes.Spec.State @using LibMatrix.Responses @using MatrixRoomUtils.LibDMSpace @using MatrixRoomUtils.LibDMSpace.StateEvents @using ArcaneLibs.Extensions @using System.Text.Json.Serialization DM Space setup tool - stage 2: Fix DM room attribution

This is just to make sure that your DMs are attributed to the right person!

@if (!string.IsNullOrWhiteSpace(Status)) {

@Status

} @if (DmSpace is not null) { @foreach (var (userId, room) in dmRooms.OrderBy(x => x.Key.Id)) { @foreach (var roomInfo in room) { Reassign } } } else { Error: DmSpaceConfiguration is null! }
Next @{ var _offset = 0; } @foreach (var (room, usersList) in duplicateDmRooms) {

Found room assigned to multiple users:

Users:

@foreach (var userProfileResponse in usersList) { Assign to
}
} @if (DmToReassign is not null) { @foreach (var userProfileResponse in roomMembers[DmToReassign]) { Assign to
}
} @code { private string newMxid { get; set; } = ""; private RoomInfo? DmToReassign { get => _dmToReassign; set { _dmToReassign = value; StateHasChanged(); } } private string? Status { get => _status; set { _status = value; StateHasChanged(); } } private string? _status; private RoomInfo? _dmToReassign; [CascadingParameter] public DMSpace? DmSpace { get; set; } private Dictionary> dmRooms { get; set; } = new(); private Dictionary> duplicateDmRooms { get; set; } = new(); private Dictionary> roomMembers { get; set; } = new(); protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); } SemaphoreSlim _semaphore = new(1, 1); protected override async Task OnParametersSetAsync() { if (DmSpace is null) return; await _semaphore.WaitAsync(); DmToReassign = null; var hs = DmSpace.Homeserver; Status = "Loading DM list from account data..."; var dms = await DmSpace.Homeserver.GetAccountDataAsync>>("m.direct"); Status = "Optimising DM list from account data..."; var joinedRooms = (await hs.GetJoinedRooms()).Select(x => x.RoomId).ToList(); foreach (var (user, rooms) in dms) { for (var i = rooms.Count - 1; i >= 0; i--) { var roomId = rooms[i]; if (!joinedRooms.Contains(roomId)) rooms.RemoveAt(i); } dms[user] = rooms.Distinct().ToList(); } dms.RemoveAll((x, y) => y is {Count: 0}); await DmSpace.Homeserver.SetAccountDataAsync("m.direct", dms); dmRooms.Clear(); Status = "DM list optimised, fetching info..."; var results = dms.Select(async x => { var (userId, rooms) = x; UserProfileWithId userProfile; try { var profile = await DmSpace.Homeserver.GetProfileAsync(userId); userProfile = new() { AvatarUrl = profile.AvatarUrl, Id = userId, DisplayName = profile.DisplayName }; } catch { userProfile = new() { AvatarUrl = "mxc://feline.support/uUxBwaboPkMGtbZcAGZaIzpK", DisplayName = userId, Id = userId }; } var roomList = new List(); var tasks = rooms.Select(x => GetRoomInfo(hs.GetRoom(x))).ToAsyncEnumerable(); await foreach (var result in tasks) roomList.Add(result); return (userProfile, roomList); // StateHasChanged(); }).ToAsyncEnumerable(); await foreach (var res in results) { dmRooms.Add(res.userProfile, res.roomList); // Status = $"Listed {dmRooms.Count} users"; } _semaphore.Release(); var duplicateDmRoomIds = new Dictionary>(); foreach (var (user, rooms) in dmRooms) { foreach (var roomInfo in rooms) { if (!duplicateDmRoomIds.ContainsKey(roomInfo.Room.RoomId)) duplicateDmRoomIds.Add(roomInfo.Room.RoomId, new()); duplicateDmRoomIds[roomInfo.Room.RoomId].Add(user); } } duplicateDmRoomIds.RemoveAll((x, y) => y.Count == 1); foreach (var (roomId, users) in duplicateDmRoomIds) { duplicateDmRooms.Add(dmRooms.First(x => x.Value.Any(x => x.Room.RoomId == roomId)).Value.First(x => x.Room.RoomId == roomId), users); } // StateHasChanged(); Status = null; await base.OnParametersSetAsync(); } private async Task Execute() { NavigationManager.NavigateTo("/User/DMSpace/Setup?stage=3"); } private async Task GetRoomInfo(GenericRoom room) { var roomInfo = new RoomInfo() { Room = room }; roomMembers[roomInfo] = new(); roomInfo.CreationEventContent = await room.GetCreateEventAsync(); try { roomInfo.RoomName = await room.GetNameAsync(); } catch { } var membersEnum = room.GetMembersAsync(); await foreach (var member in membersEnum) if (member.TypedContent is RoomMemberEventContent memberEvent && !string.IsNullOrWhiteSpace(memberEvent.Membership) && memberEvent.Membership == "join") roomMembers[roomInfo].Add(new() { DisplayName = memberEvent.DisplayName, AvatarUrl = memberEvent.AvatarUrl, Id = member.StateKey }); if (string.IsNullOrWhiteSpace(roomInfo.RoomName) || roomInfo.RoomName == room.RoomId) { List displayNames = new List(); foreach (var member in roomMembers[roomInfo]) if (!string.IsNullOrWhiteSpace(member.DisplayName)) displayNames.Add(member.DisplayName); roomInfo.RoomName = string.Join(", ", displayNames); } try { string? roomIcon = (await room.GetAvatarUrlAsync())?.Url; if (room is not null) roomInfo.RoomIcon = roomIcon; } catch { } return roomInfo; } private async Task> GetRoomInfoForRooms(List rooms) { var tasks = rooms.Select(GetRoomInfo).ToList(); await Task.WhenAll(tasks); return tasks.Select(x => x.Result).ToList(); } private async Task SetRoomAssignment(string roomId, string userId) { var hs = DmSpace.Homeserver; Status = "Loading DM list from account data..."; var dms = await DmSpace.Homeserver.GetAccountDataAsync>>("m.direct"); Status = "Updating DM list from account data..."; foreach (var (user, rooms) in dms) { rooms.RemoveAll(x => x == roomId); dms[user] = rooms.Distinct().ToList(); } if(!dms.ContainsKey(userId)) dms.Add(userId, new()); dms[userId].Add(roomId); dms.RemoveAll((x, y) => y is {Count: 0}); await DmSpace.Homeserver.SetAccountDataAsync("m.direct", dms); duplicateDmRooms.RemoveAll((x, y) => x.Room.RoomId == roomId); StateHasChanged(); if (duplicateDmRooms.Count == 0) await OnParametersSetAsync(); } private class UserProfileWithId : UserProfileResponse { [JsonIgnore] public string Id { get; set; } } }