@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.Auth; }
@if (!string.IsNullOrWhiteSpace(@session.UserInfo?.AvatarUrl)) { // Console.WriteLine($"Rendering {session.UserInfo.AvatarUrl} with homeserver {session.Homeserver}"); } else { } @* *@

Manage Remove Log out

@if (_offlineSessions.Count > 0) {

Sessions on unreachable servers

@foreach (var session in _offlineSessions) { }

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

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

Invalid sessions

@foreach (var session in _invalidSessions) { }

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

Re-login Remove
} @code { #if DEBUG private const bool _debug = true; #else private const bool _debug = false; #endif private bool Busy { get; set; } = true; private class HomepageSessionInfo : RmuSessionStore.SessionInfo { 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 RmuSessionStore.SessionInfo? _currentSession; int scannedSessions, totalSessions = 1; private SvgIdenticonGenerator _identiconGenerator = new(); protected override async Task OnInitializedAsync() { Console.WriteLine("Index.OnInitializedAsync"); logger.LogDebug("Initialising index page"); _currentSession = await sessionStore.GetCurrentSession(); _sessions.Clear(); _offlineSessions.Clear(); var sessions = await sessionStore.GetAllSessions(); scannedSessions = 0; totalSessions = sessions.Count; logger.LogDebug("Found {0} tokens", totalSessions); if (sessions is not { Count: > 0 }) { Console.WriteLine("No tokens found, trying migration from MRU..."); sessions = await sessionStore.GetAllSessions(); if (sessions is not { Count: > 0 }) { Console.WriteLine("No tokens found"); return; } } List offlineServers = []; var sema = new SemaphoreSlim(8, 8); var updateSw = Stopwatch.StartNew(); var tasks = sessions.Select(async session => { await sema.WaitAsync(); var token = session.Value.Auth; AuthenticatedHomeserverGeneric hs; try { Task serverVersionTask = Task.FromResult(new() { Server = new() { Name = "Unknown", Version = "0.0.0" } }); try { hs = await HsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); serverVersionTask = hs.FederationClient?.GetServerVersionAsync() ?? serverVersionTask!; } catch (Exception e) { logger.LogError("Failed to get info for {0} via {1}: {2}", token.UserId, token.Homeserver, e); logger.LogError("Continuing with server-less session"); hs = await HsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy, useGeneric: true, enableServer: false); } var joinedRoomsTask = hs.GetJoinedRooms(); var profileTask = hs.GetProfileAsync(hs.WhoAmI.UserId); _sessions.Add(new() { Auth = token, SessionId = session.Value.SessionId, Homeserver = hs, UserInfo = new() { AvatarUrl = (await profileTask).AvatarUrl, RoomCount = (await joinedRoomsTask).Count, DisplayName = (await profileTask).DisplayName ?? hs.WhoAmI.UserId }, ServerVersion = await (serverVersionTask ?? Task.FromResult(null)!), }); if (updateSw.ElapsedMilliseconds > 25) { 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(session.Value); } 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; Busy = false; StateHasChanged(); Console.WriteLine("Index.OnInitializedAsync finished"); } private class UserInfo { internal string? AvatarUrl { get; set; } internal string DisplayName { get; set; } internal int RoomCount { get; set; } } private async Task RemoveUser(string sessionId, bool logout = false) { try { if (logout) { var auth = (await sessionStore.GetSession(sessionId))?.Auth; 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 sessionStore.RemoveSession(sessionId); StateHasChanged(); } private async Task SwitchSession(string sessionId) { Console.WriteLine($"Switching to {sessionId}"); await sessionStore.SetCurrentSession(sessionId); _currentSession = await sessionStore.GetCurrentSession(); StateHasChanged(); } private async Task ManageUser(string sessionId) { await sessionStore.SetCurrentSession(sessionId); NavigationManager.NavigateTo("/User/Profile"); } }