MRU->RMU, fixes, cleanup
1 files changed, 191 insertions, 0 deletions
diff --git a/MatrixUtils.Web/Pages/Index.razor b/MatrixUtils.Web/Pages/Index.razor
new file mode 100644
index 0000000..9c1bab6
--- /dev/null
+++ b/MatrixUtils.Web/Pages/Index.razor
@@ -0,0 +1,191 @@
+@page "/"
+@inject ILogger<Index> logger
+@using LibMatrix.Responses
+@using LibMatrix
+@using LibMatrix.Homeservers
+@using ArcaneLibs.Extensions
+@using MatrixUtils.Web.Pages.Dev
+
+<PageTitle>Index</PageTitle>
+
+<h3>Rory&::MatrixUtils</h3>
+Small collection of tools to do not-so-everyday things.
+
+<br/><br/>
+<h5>Signed in accounts - <a href="/Login">Add new account</a></h5>
+<hr/>
+<form>
+ <table>
+ @foreach (var session in _sessions.OrderByDescending(x => x.UserInfo.RoomCount)) {
+ var _auth = session.UserAuth;
+ <tr class="user-entry">
+ <td>
+ <img class="avatar" src="@session.UserInfo.AvatarUrl"/>
+ </td>
+ <td class="user-info">
+ <p>
+ <input type="radio" name="csa" checked="@(_currentSession.AccessToken == _auth.AccessToken)" @onclick="@(() => SwitchSession(_auth))" style="text-decoration-line: unset;"/>
+ <b>@session.UserInfo.DisplayName</b> on <b>@_auth.Homeserver</b><br/>
+ </p>
+ <span style="display: inline-block; width: 128px;">@session.UserInfo.RoomCount rooms</span>
+ <a style="color: #888888" href="@("/ServerInfo/" + session.Homeserver.ServerName + "/")">@session.ServerVersion.Server.Name @session.ServerVersion.Server.Version</a>
+ @if (_auth.Proxy != null) {
+ <span class="badge badge-info"> (proxied via @_auth.Proxy)</span>
+ }
+ else {
+ <p>Not proxied</p>
+ }
+ @if (_debug) {
+ <p>T=@session.Homeserver.GetType().FullName</p>
+ <p>D=@session.Homeserver.WhoAmI.DeviceId</p>
+ <p>U=@session.Homeserver.WhoAmI.UserId</p>
+ }
+ </td>
+ <td>
+ <p>
+ <LinkButton OnClick="@(() => ManageUser(_auth))">Manage</LinkButton>
+ <LinkButton OnClick="@(() => RemoveUser(_auth))">Remove</LinkButton>
+ <LinkButton OnClick="@(() => RemoveUser(_auth, true))">Log out</LinkButton>
+ </p>
+ </td>
+ </tr>
+ }
+ </table>
+</form>
+
+@if (_offlineSessions.Count > 0) {
+ <br/>
+ <br/>
+ <h5>Sessions on unreachable servers</h5>
+ <hr/>
+ <form>
+ <table>
+ @foreach (var session in _offlineSessions) {
+ <tr class="user-entry">
+ <td>
+ <p>
+ @{
+ string[] parts = session.UserId.Split(':');
+ }
+ <span>@parts[0][1..]</span> on <span>@parts[1]</span>
+ @if (!string.IsNullOrWhiteSpace(session.Proxy)) {
+ <span class="badge badge-info"> (proxied via @session.Proxy)</span>
+ }
+ </p>
+ </td>
+ <td>
+ <LinkButton OnClick="@(() => RemoveUser(session))">Remove</LinkButton>
+ </td>
+ </tr>
+ }
+ </table>
+ </form>
+}
+
+@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 Dictionary<UserAuth, UserInfo> _users = new();
+ private readonly List<AuthInfo> _sessions = [];
+ private readonly List<UserAuth> _offlineSessions = [];
+ private LoginResponse? _currentSession;
+
+ protected override async Task OnInitializedAsync() {
+ Console.WriteLine("Index.OnInitializedAsync");
+ _currentSession = await RMUStorage.GetCurrentToken();
+ _sessions.Clear();
+ _offlineSessions.Clear();
+ var tokens = await RMUStorage.GetAllTokens();
+ var profileTasks = tokens.Select(async token => {
+ UserInfo userInfo = new();
+ AuthenticatedHomeserverGeneric hs;
+ Console.WriteLine($"Getting hs for {token.ToJson()}");
+ try {
+ hs = await hsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy);
+ }
+ catch (MatrixException e) {
+ if (e.ErrorCode != "M_UNKNOWN_TOKEN") throw;
+ NavigationManager.NavigateTo("/InvalidSession?ctx=" + token.AccessToken);
+ return;
+
+ }
+ catch (Exception e) {
+ logger.LogError(e, $"Failed to instantiate AuthenticatedHomeserver for {token.ToJson()}, homeserver may be offline?", token.UserId);
+ _offlineSessions.Add(token);
+ return;
+ }
+
+ Console.WriteLine($"Got hs for {token.ToJson()}");
+
+ var roomCountTask = hs.GetJoinedRooms();
+ var profile = await hs.GetProfileAsync(hs.WhoAmI.UserId);
+ userInfo.DisplayName = profile.DisplayName ?? hs.WhoAmI.UserId;
+ Console.WriteLine(profile.ToJson());
+ _sessions.Add(new() {
+ UserInfo = new() {
+ AvatarUrl = string.IsNullOrWhiteSpace(profile.AvatarUrl) ? "https://api.dicebear.com/6.x/identicon/svg?seed=" + hs.WhoAmI.UserId : hs.ResolveMediaUri(profile.AvatarUrl),
+ RoomCount = (await roomCountTask).Count,
+ DisplayName = profile.DisplayName ?? hs.WhoAmI.UserId
+ },
+ UserAuth = token,
+ ServerVersion = await (hs.FederationClient?.GetServerVersionAsync() ?? Task.FromResult<ServerVersionResponse?>(null)),
+ Homeserver = hs
+ });
+ });
+ Console.WriteLine("Waiting for profile tasks");
+ await Task.WhenAll(profileTasks);
+ Console.WriteLine("Done waiting for profile tasks");
+ 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());
+ await OnInitializedAsync();
+ }
+
+
+ private async Task SwitchSession(UserAuth auth) {
+ Console.WriteLine($"Switching to {auth.Homeserver} {auth.UserId} via {auth.Proxy}");
+ await RMUStorage.SetCurrentToken(auth);
+ await OnInitializedAsync();
+ }
+
+ private async Task ManageUser(UserAuth auth) {
+ await SwitchSession(auth);
+ NavigationManager.NavigateTo("/User/Profile");
+ }
+}
\ No newline at end of file
|