@page "/" @inject ILogger logger @using LibMatrix.Responses @using LibMatrix @using ArcaneLibs @using System.Diagnostics Index

Rory&::MatrixUtils

Small collection of tools to do not-so-everyday things.

@totalSessions signed in sessions - Add new account
@if (scannedSessions != totalSessions) { @scannedSessions/@totalSessions }
@foreach (var session in _sessions.OrderByDescending(x => x.UserInfo.RoomCount)) { var _auth = session.UserAuth; }

Manage Remove Log out

@if (_offlineSessions.Count > 0) {

Sessions on unreachable servers

@foreach (var session in _offlineSessions) { }

@{ string[] parts = session.UserId.Split(':'); } @parts[0][1..] on @parts[1] @if (!string.IsNullOrWhiteSpace(session.Proxy)) { (proxied via @session.Proxy) }

Remove
} @if (_invalidSessions.Count > 0) {

Invalid sessions

@foreach (var session in _invalidSessions) { }

@{ string[] parts = session.UserId.Split(':'); } @parts[0][1..] on @parts[1] @if (!string.IsNullOrWhiteSpace(session.Proxy)) { (proxied via @session.Proxy) }

Remove
} @code { #if DEBUG private const bool _debug = true; #else private const bool _debug = false; #endif private class AuthInfo { public UserAuth? UserAuth { get; set; } public UserInfo? UserInfo { get; set; } public ServerVersionResponse? ServerVersion { get; set; } public AuthenticatedHomeserverGeneric? Homeserver { get; set; } } private readonly List _sessions = []; private readonly List _offlineSessions = []; private readonly List _invalidSessions = []; private LoginResponse? _currentSession; int scannedSessions = 0, totalSessions = 1; private SvgIdenticonGenerator _identiconGenerator = new(); protected override async Task OnInitializedAsync() { Console.WriteLine("Index.OnInitializedAsync"); logger.LogDebug("Initialising index page"); _currentSession = await RMUStorage.GetCurrentToken(); _sessions.Clear(); _offlineSessions.Clear(); var tokens = await RMUStorage.GetAllTokens(); scannedSessions = 0; totalSessions = tokens.Count; logger.LogDebug("Found {0} tokens", totalSessions); if (tokens is not { Count: > 0 }) { Console.WriteLine("No tokens found, trying migration from MRU..."); await RMUStorage.MigrateFromMRU(); tokens = await RMUStorage.GetAllTokens(); if (tokens is not { Count: > 0 }) { Console.WriteLine("No tokens found"); return; } } List offlineServers = []; var sema = new SemaphoreSlim(64, 64); var updateSw = Stopwatch.StartNew(); var tasks = tokens.Select(async token => { await sema.WaitAsync(); if ((!string.IsNullOrWhiteSpace(token.Proxy) && offlineServers.Contains(token.Proxy)) || offlineServers.Contains(token.Homeserver)) { _offlineSessions.Add(token); sema.Release(); scannedSessions++; return; } AuthenticatedHomeserverGeneric hs; try { hs = await hsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); var joinedRoomsTask = hs.GetJoinedRooms(); var profileTask = hs.GetProfileAsync(hs.WhoAmI.UserId); var serverVersionTask = hs.FederationClient?.GetServerVersionAsync(); _sessions.Add(new() { UserInfo = new() { AvatarUrl = string.IsNullOrWhiteSpace((await profileTask).AvatarUrl) ? _identiconGenerator.GenerateAsDataUri(hs.WhoAmI.UserId) : hs.ResolveMediaUri((await profileTask).AvatarUrl), RoomCount = (await joinedRoomsTask).Count, DisplayName = (await profileTask).DisplayName ?? hs.WhoAmI.UserId }, UserAuth = token, ServerVersion = await (serverVersionTask ?? Task.FromResult(null)!), Homeserver = hs }); if (updateSw.ElapsedMilliseconds > 250) { updateSw.Restart(); StateHasChanged(); } } catch (MatrixException e) { if (e is { ErrorCode: "M_UNKNOWN_TOKEN" }) { logger.LogWarning("Got unknown token error for {0} via {1}", token.UserId, token.Homeserver); _invalidSessions.Add(token); } else { logger.LogError("Failed to get info for {0} via {1}: {2}", token.UserId, token.Homeserver, e); throw; } } catch (Exception e) { logger.LogError("Failed to get info for {0} via {1}: {2}", token.UserId, token.Homeserver, e); if (!string.IsNullOrWhiteSpace(token.Proxy)) { offlineServers.Add(token.Proxy); sema.Release(); return; } offlineServers.Add(token.Homeserver); } scannedSessions++; sema.Release(); }).ToList(); await Task.WhenAll(tasks); scannedSessions = totalSessions; await base.OnInitializedAsync(); } private class UserInfo { internal string AvatarUrl { get; set; } internal string DisplayName { get; set; } internal int RoomCount { get; set; } } private async Task RemoveUser(UserAuth auth, bool logout = false) { try { if (logout) { await (await hsProvider.GetAuthenticatedWithToken(auth.Homeserver, auth.AccessToken, auth.Proxy)).Logout(); } } catch (Exception e) { if (e is MatrixException { ErrorCode: "M_UNKNOWN_TOKEN" }) { //todo: handle this return; } Console.WriteLine(e); } await RMUStorage.RemoveToken(auth); if ((await RMUStorage.GetCurrentToken())?.AccessToken == auth.AccessToken) await RMUStorage.SetCurrentToken((await RMUStorage.GetAllTokens() ?? throw new InvalidOperationException()).FirstOrDefault()); StateHasChanged(); } private async Task SwitchSession(UserAuth auth) { Console.WriteLine($"Switching to {auth.Homeserver} {auth.UserId} via {auth.Proxy}"); await RMUStorage.SetCurrentToken(auth); _currentSession = auth; StateHasChanged(); } private async Task ManageUser(UserAuth auth) { await SwitchSession(auth); NavigationManager.NavigateTo("/User/Profile"); } }