MatrixRoomUtils

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit 3d3edeae16252a311704b390cfad6faa435a8b84
parent 5ad6fcf24b37fed7340ff1a4a8b7707902ef743d
Author: TheArcaneBrony <myrainbowdash949@gmail.com>
Date:   Wed,  3 May 2023 18:40:53 +0200

Refactor

Diffstat:
AMatrixRoomUtils.Core/AuthenticatedHomeServer.cs | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
DMatrixRoomUtils.Core/Authentication/MatrixAccount.cs | 94-------------------------------------------------------------------------------
AMatrixRoomUtils.Core/Authentication/MatrixAuth.cs | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AMatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs | 20++++++++++++++++++++
MMatrixRoomUtils.Core/Extensions/StringExtensions.cs | 2+-
AMatrixRoomUtils.Core/Interfaces/IHomeServer.cs | 38++++++++++++++++++++++++++++++++++++++
AMatrixRoomUtils.Core/RatelimitedHttpClient.cs | 8++++++++
MMatrixRoomUtils.Core/Responses/LoginResponse.cs | 2+-
AMatrixRoomUtils.Core/Room.cs | 45+++++++++++++++++++++++++++++++++++++++++++++
AMatrixRoomUtils.Core/RuntimeCache.cs | 29+++++++++++++++++++++++++++++
AMatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs | 36++++++++++++++++++++++++++++++++++++
DMatrixRoomUtils.Web/Classes/RuntimeStorage.cs | 56--------------------------------------------------------
MMatrixRoomUtils.Web/Pages/DataExportPage.razor | 28++++++++++++----------------
MMatrixRoomUtils.Web/Pages/Index.razor | 10+++++-----
MMatrixRoomUtils.Web/Pages/LoginPage.razor | 12++++++------
MMatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor | 8++++----
MMatrixRoomUtils.Web/Pages/PolicyListRoomList.razor | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
AMatrixRoomUtils.Web/Pages/RoomStateEditorPage.razor | 178+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MMatrixRoomUtils.Web/Pages/RoomStateRoomList.razor | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
MMatrixRoomUtils.Web/Pages/RoomStateViewerPage.razor | 8++++----
MMatrixRoomUtils.Web/Pages/UserImportPage.razor | 14++++++--------
MMatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor | 13+++++++------
MMatrixRoomUtils.Web/Shared/MainLayout.razor | 4++--
23 files changed, 664 insertions(+), 240 deletions(-)

diff --git a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs @@ -0,0 +1,53 @@ +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text.Json; + +namespace MatrixRoomUtils; + +public class AuthenticatedHomeServer : IHomeServer +{ + public string UserId { get; set; } + public string AccessToken { get; set; } + + public AuthenticatedHomeServer(string userId, string accessToken, string canonicalHomeServerDomain) + { + UserId = userId; + AccessToken = accessToken; + HomeServerDomain = canonicalHomeServerDomain; + _httpClient = new HttpClient(); + + var rhsfwt = ResolveHomeserverFromWellKnown(canonicalHomeServerDomain); + rhsfwt.ContinueWith(_ => + { + FullHomeServerDomain = rhsfwt.Result; + _httpClient.Dispose(); + _httpClient = new HttpClient {BaseAddress = new Uri(FullHomeServerDomain)}; + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken); + Console.WriteLine("[AHS] Finished setting up http client :)"); + }); + } + + public async Task<Room> GetRoom(string roomId) + { + return new Room(_httpClient, roomId); + } + + public async Task<List<Room>> GetJoinedRooms() + { + var rooms = new List<Room>(); + var _rooms = await _httpClient.GetAsync("/_matrix/client/v3/joined_rooms"); + if (!_rooms.IsSuccessStatusCode) + { + Console.WriteLine($"Failed to get rooms: {await _rooms.Content.ReadAsStringAsync()}"); + throw new InvalidDataException($"Failed to get rooms: {await _rooms.Content.ReadAsStringAsync()}"); + } + + var roomsJson = await _rooms.Content.ReadFromJsonAsync<JsonElement>(); + foreach (var room in roomsJson.GetProperty("joined_rooms").EnumerateArray()) + { + rooms.Add(new Room(_httpClient, room.GetString())); + } + + return rooms; + } +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Core/Authentication/MatrixAccount.cs b/MatrixRoomUtils.Core/Authentication/MatrixAccount.cs @@ -1,93 +0,0 @@ -using System.Net.Http.Json; -using System.Text.Json; -using MatrixRoomUtils.Responses; - -namespace MatrixRoomUtils.Authentication; - -public class MatrixAccount -{ - public static async Task<LoginResponse> Login(string homeserver, string username, string password) - { - Console.WriteLine($"Logging in to {homeserver} as {username}..."); - homeserver = await ResolveHomeserverFromWellKnown(homeserver); - var hc = new HttpClient(); - var payload = new - { - type = "m.login.password", - identifier = new - { - type = "m.id.user", - user = username - }, - password = password, - initial_device_display_name = "Rory&::MatrixRoomUtils" - }; - Console.WriteLine($"Sending login request to {homeserver}..."); - var resp = await hc.PostAsJsonAsync($"{homeserver}/_matrix/client/r0/login", payload); - Console.WriteLine($"Login: {resp.StatusCode}"); - var data = await resp.Content.ReadFromJsonAsync<JsonElement>(); - if (!resp.IsSuccessStatusCode) Console.WriteLine("Login: " + data.ToString()); - if (data.TryGetProperty("retry_after_ms", out var retryAfter)) - { - Console.WriteLine($"Login: Waiting {retryAfter.GetInt32()}ms before retrying"); - await Task.Delay(retryAfter.GetInt32()); - return await Login(homeserver, username, password); - } - - return data.Deserialize<LoginResponse>(); - //var token = data.GetProperty("access_token").GetString(); - //return token; - } - - public static async Task<ProfileResponse> GetProfile(string homeserver, string mxid) - { - Console.WriteLine($"Fetching profile for {mxid} on {homeserver}..."); - homeserver = await ResolveHomeserverFromWellKnown(homeserver); - var hc = new HttpClient(); - var resp = await hc.GetAsync($"{homeserver}/_matrix/client/r0/profile/{mxid}"); - var data = await resp.Content.ReadFromJsonAsync<JsonElement>(); - if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data.ToString()); - return data.Deserialize<ProfileResponse>(); - } - - public static async Task<string> ResolveHomeserverFromWellKnown(string homeserver) - { - using var hc = new HttpClient(); - Console.WriteLine($"Resolving homeserver: {homeserver}"); - if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver; - - if (await CheckSuccessStatus($"{homeserver}/.well-known/matrix/client")) - { - var resp = await hc.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/client"); - var hs = resp.GetProperty("m.homeserver").GetProperty("base_url").GetString(); - return hs; - } - Console.WriteLine($"No client well-known..."); - if (await CheckSuccessStatus($"{homeserver}/.well-known/matrix/server")) - { - var resp = await hc.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/server"); - var hs = resp.GetProperty("m.server").GetString(); - return hs; - } - Console.WriteLine($"No server well-known..."); - if (await CheckSuccessStatus($"{homeserver}/_matrix/client/versions")) return homeserver; - Console.WriteLine($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); - throw new InvalidDataException($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); - } - - private static async Task<bool> CheckSuccessStatus(string url) - { - //cors causes failure, try to catch - try - { - using var hc = new HttpClient(); - var resp = await hc.GetAsync(url); - return resp.IsSuccessStatusCode; - } - catch (Exception e) - { - Console.WriteLine($"Failed to check success status: {e.Message}"); - return false; - } - } -} -\ No newline at end of file diff --git a/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs b/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs @@ -0,0 +1,94 @@ +using System.Net.Http.Json; +using System.Text.Json; +using MatrixRoomUtils.Responses; + +namespace MatrixRoomUtils.Authentication; + +public class MatrixAuth +{ + public static async Task<LoginResponse> Login(string homeserver, string username, string password) + { + Console.WriteLine($"Logging in to {homeserver} as {username}..."); + homeserver = await ResolveHomeserverFromWellKnown(homeserver); + var hc = new HttpClient(); + var payload = new + { + type = "m.login.password", + identifier = new + { + type = "m.id.user", + user = username + }, + password = password, + initial_device_display_name = "Rory&::MatrixRoomUtils" + }; + Console.WriteLine($"Sending login request to {homeserver}..."); + var resp = await hc.PostAsJsonAsync($"{homeserver}/_matrix/client/r0/login", payload); + Console.WriteLine($"Login: {resp.StatusCode}"); + var data = await resp.Content.ReadFromJsonAsync<JsonElement>(); + if (!resp.IsSuccessStatusCode) Console.WriteLine("Login: " + data.ToString()); + if (data.TryGetProperty("retry_after_ms", out var retryAfter)) + { + Console.WriteLine($"Login: Waiting {retryAfter.GetInt32()}ms before retrying"); + await Task.Delay(retryAfter.GetInt32()); + return await Login(homeserver, username, password); + } + + return data.Deserialize<LoginResponse>(); + //var token = data.GetProperty("access_token").GetString(); + //return token; + } + + public static async Task<ProfileResponse> GetProfile(string homeserver, string mxid) + { + Console.WriteLine($"Fetching profile for {mxid} on {homeserver}..."); + homeserver = await ResolveHomeserverFromWellKnown(homeserver); + using var hc = new HttpClient(); + var resp = await hc.GetAsync($"{homeserver}/_matrix/client/r0/profile/{mxid}"); + var data = await resp.Content.ReadFromJsonAsync<JsonElement>(); + if (!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data.ToString()); + return data.Deserialize<ProfileResponse>(); + } + + [Obsolete("Use IHomeServer")] + public static async Task<string> ResolveHomeserverFromWellKnown(string homeserver) + { + using var hc = new HttpClient(); + Console.WriteLine($"Resolving homeserver: {homeserver}"); + if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver; + + if (await CheckSuccessStatus($"{homeserver}/.well-known/matrix/client")) + { + var resp = await hc.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/client"); + var hs = resp.GetProperty("m.homeserver").GetProperty("base_url").GetString(); + return hs; + } + Console.WriteLine($"No client well-known..."); + if (await CheckSuccessStatus($"{homeserver}/.well-known/matrix/server")) + { + var resp = await hc.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/server"); + var hs = resp.GetProperty("m.server").GetString(); + return hs; + } + Console.WriteLine($"No server well-known..."); + if (await CheckSuccessStatus($"{homeserver}/_matrix/client/versions")) return homeserver; + Console.WriteLine($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); + throw new InvalidDataException($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); + } + + private static async Task<bool> CheckSuccessStatus(string url) + { + //cors causes failure, try to catch + try + { + using var hc = new HttpClient(); + var resp = await hc.GetAsync(url); + return resp.IsSuccessStatusCode; + } + catch (Exception e) + { + Console.WriteLine($"Failed to check success status: {e.Message}"); + return false; + } + } +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs @@ -0,0 +1,19 @@ +namespace MatrixRoomUtils.Extensions; + +public static class HttpClientExtensions +{ + public static async Task<bool> CheckSuccessStatus(this HttpClient hc, string url) + { + //cors causes failure, try to catch + try + { + var resp = await hc.GetAsync(url); + return resp.IsSuccessStatusCode; + } + catch (Exception e) + { + Console.WriteLine($"Failed to check success status: {e.Message}"); + return false; + } + } +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Core/Extensions/StringExtensions.cs b/MatrixRoomUtils.Core/Extensions/StringExtensions.cs @@ -11,7 +11,7 @@ public static class StringExtensions var server = MxcUrl.Split('/')[2]; var mediaId = MxcUrl.Split('/')[3]; - return $"{await MatrixAccount.ResolveHomeserverFromWellKnown(server)}/_matrix/media/v3/download/{server}/{mediaId}"; + return $"{await MatrixAuth.ResolveHomeserverFromWellKnown(server)}/_matrix/media/v3/download/{server}/{mediaId}"; } } \ No newline at end of file diff --git a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs @@ -0,0 +1,37 @@ +using System.Net.Http.Json; +using System.Text.Json; +using MatrixRoomUtils.Extensions; + +namespace MatrixRoomUtils; + +public class IHomeServer +{ + public string HomeServerDomain { get; set; } + public string FullHomeServerDomain { get; set; } + + private protected HttpClient _httpClient { get; set; } = new(); + public async Task<string> ResolveHomeserverFromWellKnown(string homeserver) + { + Console.WriteLine($"Resolving homeserver: {homeserver}"); + if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver; + if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/client")) + { + Console.WriteLine($"Got successful response for client well-known..."); + var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/client"); + Console.WriteLine($"Response: {resp.ToString()}"); + var hs = resp.GetProperty("m.homeserver").GetProperty("base_url").GetString(); + return hs; + } + Console.WriteLine($"No client well-known..."); + if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/server")) + { + var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/server"); + var hs = resp.GetProperty("m.server").GetString(); + return hs; + } + Console.WriteLine($"No server well-known..."); + if (await _httpClient.CheckSuccessStatus($"{homeserver}/_matrix/client/versions")) return homeserver; + Console.WriteLine($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); + throw new InvalidDataException($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); + } +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Core/RatelimitedHttpClient.cs b/MatrixRoomUtils.Core/RatelimitedHttpClient.cs @@ -0,0 +1,7 @@ +namespace MatrixRoomUtils; + +public class RatelimitedHttpClient : HttpClient +{ + + +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Core/Responses/LoginResponse.cs b/MatrixRoomUtils.Core/Responses/LoginResponse.cs @@ -26,6 +26,6 @@ public class LoginResponse } public async Task<string> GetCanonicalHomeserverUrl() { - return await MatrixAccount.ResolveHomeserverFromWellKnown(HomeServer); + return await MatrixAuth.ResolveHomeserverFromWellKnown(HomeServer); } } \ No newline at end of file diff --git a/MatrixRoomUtils.Core/Room.cs b/MatrixRoomUtils.Core/Room.cs @@ -0,0 +1,44 @@ +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text.Json; + +namespace MatrixRoomUtils; + +public class Room +{ + private readonly HttpClient _httpClient; + public string RoomId { get; set; } + + public Room(HttpClient httpClient, string roomId) + { + _httpClient = httpClient; + RoomId = roomId; + } + + public async Task<JsonElement?> GetStateAsync(string type, string state_key="") + { + Console.WriteLine($"{RoomId}::_qry[{type}::{state_key}]"); + var res = await _httpClient.GetAsync($"/_matrix/client/r0/rooms/{RoomId}/state/{type}/{state_key}"); + if (!res.IsSuccessStatusCode) + { + Console.WriteLine($"{RoomId}::_qry[{type}::{state_key}]->status=={res.StatusCode}"); + return null; + } + return await res.Content.ReadFromJsonAsync<JsonElement>(); + } + public async Task<string?> GetNameAsync() + { + Console.WriteLine($"{RoomId}::_qry_name"); + var res = await GetStateAsync("m.room.name"); + if (!res.HasValue) + { + Console.WriteLine($"{RoomId}::_qry_name->null"); + return null; + } + Console.WriteLine($"{RoomId}::_qry_name->{res.Value.ToString()}"); + var resn = res?.GetProperty("name").GetString(); + Console.WriteLine($"Got name: {resn}"); + return resn; + } + +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Core/RuntimeCache.cs b/MatrixRoomUtils.Core/RuntimeCache.cs @@ -0,0 +1,29 @@ +using MatrixRoomUtils.Authentication; +using MatrixRoomUtils.Responses; + +namespace MatrixRoomUtils; + +public class RuntimeCache +{ + public static bool WasLoaded = false; + public static string AccessToken { get; set; } + public static string? CurrentHomeserver { get; set; } + public static AuthenticatedHomeServer CurrentHomeServer { get; set; } + public static Dictionary<string, UserInfo> LoginSessions { get; set; } = new(); + + public static Dictionary<string, HomeServerResolutionResult> HomeserverResolutionCache { get; set; } = new(); + public static Dictionary<string, (DateTime cachedAt, ProfileResponse response)> ProfileCache { get; set; } = new(); +} + + +public class UserInfo +{ + public ProfileResponse Profile { get; set; } = new(); + public LoginResponse LoginResponse { get; set; } +} + +public class HomeServerResolutionResult +{ + public string Result { get; set; } + public DateTime ResolutionTime { get; set; } +} diff --git a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs @@ -0,0 +1,35 @@ +using Blazored.LocalStorage; +using MatrixRoomUtils.Authentication; +using MatrixRoomUtils.Responses; + +namespace MatrixRoomUtils.Web.Classes; + +public partial class LocalStorageWrapper +{ + //some basic logic + public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) + { + RuntimeCache.AccessToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.token"); + RuntimeCache.CurrentHomeserver = await localStorage.GetItemAsync<string>("rory.matrixroomutils.current_homeserver"); + RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.user_cache") ?? new(); + RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new(); + Console.WriteLine($"[LocalStorageWrapper] Loaded {RuntimeCache.LoginSessions.Count} login sessions, {RuntimeCache.HomeserverResolutionCache.Count} homeserver resolution cache entries"); + if (RuntimeCache.AccessToken != null && RuntimeCache.CurrentHomeserver != null) + { + Console.WriteLine($"Access token and current homeserver are not null, creating authenticated home server"); + RuntimeCache.CurrentHomeServer = new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.AccessToken].LoginResponse.UserId, RuntimeCache.AccessToken, RuntimeCache.LoginSessions[RuntimeCache.AccessToken].LoginResponse.HomeServer); + Console.WriteLine("Created authenticated home server"); + } + RuntimeCache.WasLoaded = true; + } + + public static async Task SaveToLocalStorage(ILocalStorageService localStorage) + { + await localStorage.SetItemAsStringAsync("rory.matrixroomutils.token", RuntimeCache.AccessToken); + await localStorage.SetItemAsync("rory.matrixroomutils.current_homeserver", RuntimeCache.CurrentHomeserver); + await localStorage.SetItemAsync("rory.matrixroomutils.user_cache", RuntimeCache.LoginSessions); + await localStorage.SetItemAsync("rory.matrixroomutils.homeserver_resolution_cache", + RuntimeCache.HomeserverResolutionCache.DistinctBy(x => x.Key) + .ToDictionary(x => x.Key, x => x.Value)); + } +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Web/Classes/RuntimeStorage.cs b/MatrixRoomUtils.Web/Classes/RuntimeStorage.cs @@ -1,55 +0,0 @@ -using Blazored.LocalStorage; -using MatrixRoomUtils.Authentication; -using MatrixRoomUtils.Responses; - -namespace MatrixRoomUtils.Web.Classes; - -public class RuntimeStorage -{ - public static bool WasLoaded = false; - public static UserInfo? CurrentUserInfo { get; set; } - public static string AccessToken { get; set; } - public static string? CurrentHomeserver { get; set; } - - public static List<string> AccessTokens { get; set; } = new(); - //public static AppSettings AppSettings { get; set; } = new(); - - public static Dictionary<string, UserInfo> UsersCache { get; set; } = new(); - - public static Dictionary<string, HomeServerResolutionResult> HomeserverResolutionCache { get; set; } = new(); - - - //some basic logic - public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) - { - AccessToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.token"); - CurrentHomeserver = await localStorage.GetItemAsync<string>("rory.matrixroomutils.current_homeserver"); - AccessTokens = await localStorage.GetItemAsync<List<string>>("rory.matrixroomutils.tokens") ?? new(); - UsersCache = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.user_cache") ?? new(); - HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new(); - WasLoaded = true; - } - - public static async Task SaveToLocalStorage(ILocalStorageService localStorage) - { - await localStorage.SetItemAsStringAsync("rory.matrixroomutils.token", AccessToken); - await localStorage.SetItemAsync("rory.matrixroomutils.current_homeserver", CurrentHomeserver); - await localStorage.SetItemAsync("rory.matrixroomutils.tokens", AccessTokens); - await localStorage.SetItemAsync("rory.matrixroomutils.user_cache", UsersCache); - await localStorage.SetItemAsync("rory.matrixroomutils.homeserver_resolution_cache", - HomeserverResolutionCache.DistinctBy(x => x.Key) - .ToDictionary(x => x.Key, x => x.Value)); - } -} - -public class UserInfo -{ - public ProfileResponse Profile { get; set; } = new(); - public LoginResponse LoginResponse { get; set; } -} - -public class HomeServerResolutionResult -{ - public string Result { get; set; } - public DateTime ResolutionTime { get; set; } -} -\ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/DataExportPage.razor b/MatrixRoomUtils.Web/Pages/DataExportPage.razor @@ -17,13 +17,13 @@ <hr/> @if (_isLoaded) { -@foreach (var (token, user) in RuntimeStorage.UsersCache) +@foreach (var (token, user) in RuntimeCache.LoginSessions) { <IndexUserItem User="@user" Token="@token"/> <pre> @user.LoginResponse.UserId[1..].Split(":")[0]\auth\access_token=@token @user.LoginResponse.UserId[1..].Split(":")[0]\auth\device_id=@user.LoginResponse.DeviceId -@user.LoginResponse.UserId[1..].Split(":")[0]\auth\home_server=@(RuntimeStorage.HomeserverResolutionCache.ContainsKey(user.LoginResponse.HomeServer) ? RuntimeStorage.HomeserverResolutionCache[user.LoginResponse.HomeServer].Result : "loading...") +@user.LoginResponse.UserId[1..].Split(":")[0]\auth\home_server=@(RuntimeCache.HomeserverResolutionCache.ContainsKey(user.LoginResponse.HomeServer) ? RuntimeCache.HomeserverResolutionCache[user.LoginResponse.HomeServer].Result : "loading...") @user.LoginResponse.UserId[1..].Split(":")[0]\auth\user_id=@@@user.LoginResponse.UserId @user.LoginResponse.UserId[1..].Split(":")[0]\user\automatically_share_keys_with_trusted_users=true @user.LoginResponse.UserId[1..].Split(":")[0]\user\muted_tags=global @@ -46,29 +46,25 @@ else protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); - if (!RuntimeStorage.WasLoaded) + if (!RuntimeCache.WasLoaded) { - Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!"); - await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); - Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); - - var homeservers = RuntimeStorage.UsersCache.Values.Select(x => x.LoginResponse.HomeServer).Distinct(); + var homeservers = RuntimeCache.LoginSessions.Values.Select(x => x.LoginResponse.HomeServer).Distinct(); totalHomeservers = homeservers.Count(); StateHasChanged(); foreach (var hs in homeservers) { - if (RuntimeStorage.HomeserverResolutionCache.ContainsKey(hs)) continue; - var resolvedHomeserver = await MatrixAccount.ResolveHomeserverFromWellKnown(hs); + if (LocalStorageWrapper.HomeserverResolutionCache.ContainsKey(hs)) continue; + var resolvedHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(hs); - if (RuntimeStorage.HomeserverResolutionCache.ContainsKey(hs)) - RuntimeStorage.HomeserverResolutionCache.Remove(hs); - RuntimeStorage.HomeserverResolutionCache.Add(hs, new(){Result = resolvedHomeserver, ResolutionTime = DateTime.Now}); - await RuntimeStorage.SaveToLocalStorage(LocalStorage); + if (LocalStorageWrapper.HomeserverResolutionCache.ContainsKey(hs)) + LocalStorageWrapper.HomeserverResolutionCache.Remove(hs); + LocalStorageWrapper.HomeserverResolutionCache.Add(hs, new() { Result = resolvedHomeserver, ResolutionTime = DateTime.Now }); + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); Console.WriteLine("Saved to local storage:"); - Console.WriteLine(JsonSerializer.Serialize(RuntimeStorage.HomeserverResolutionCache, new JsonSerializerOptions() + Console.WriteLine(JsonSerializer.Serialize(LocalStorageWrapper.HomeserverResolutionCache, new JsonSerializerOptions() { WriteIndented = true })); diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor @@ -14,19 +14,19 @@ Small collection of tools to do not-so-everyday things. <h5>Signed in accounts - <a href="/Login">Add new account</a> or <a href="/ImportUsers">Import from TSV</a></h5> <hr/> @{ - Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); - if (!RuntimeStorage.WasLoaded) + Console.WriteLine("Users in cache: " + LocalStorageWrapper.LoginSessions.Count); + if (!LocalStorageWrapper.WasLoaded) { Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!"); - RuntimeStorage.LoadFromLocalStorage(LocalStorage).GetAwaiter().OnCompleted(() => + LocalStorageWrapper.LoadFromLocalStorage(LocalStorage).GetAwaiter().OnCompleted(() => { - Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); + Console.WriteLine("Users in cache: " + LocalStorageWrapper.LoginSessions.Count); StateHasChanged(); }); } } <form> - @foreach (var (token, user) in RuntimeStorage.UsersCache) + @foreach (var (token, user) in LocalStorageWrapper.LoginSessions) { <IndexUserItem User="@user" Token="@token"/> } diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor @@ -25,22 +25,22 @@ string password = ""; async Task Login() { - var result = await MatrixAccount.Login(homeserver, username, password); + var result = await MatrixAuth.Login(homeserver, username, password); Console.WriteLine($"Obtained access token for {result.UserId}!"); - RuntimeStorage.AccessToken = result.AccessToken; + LocalStorageWrapper.AccessToken = result.AccessToken; var userinfo = new UserInfo() { LoginResponse = result }; - userinfo.Profile = await MatrixAccount.GetProfile(result.HomeServer, result.UserId); + userinfo.Profile = await MatrixAuth.GetProfile(result.HomeServer, result.UserId); - RuntimeStorage.UsersCache.Add(result.AccessToken, userinfo); - RuntimeStorage.CurrentHomeserver = await MatrixAccount.ResolveHomeserverFromWellKnown(result.HomeServer); + LocalStorageWrapper.LoginSessions.Add(result.AccessToken, userinfo); + LocalStorageWrapper.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(result.HomeServer); - await RuntimeStorage.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); } } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor @@ -195,9 +195,9 @@ else protected override async Task OnInitializedAsync() { - if (!RuntimeStorage.WasLoaded) await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + if (!LocalStorageWrapper.WasLoaded) await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if(RuntimeStorage.AccessToken == null || RuntimeStorage.CurrentHomeserver == null) + if(LocalStorageWrapper.AccessToken == null || LocalStorageWrapper.CurrentHomeserver == null) { NavigationManager.NavigateTo("/Login"); return; @@ -210,8 +210,8 @@ else private async Task LoadStatesAsync() { using var client = new HttpClient(); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); - var response = await client.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); var content = await response.Content.ReadAsStringAsync(); // Console.WriteLine(JsonSerializer.Deserialize<object>(content).ToJson()); var stateEvents = JsonSerializer.Deserialize<List<StateEvent>>(content); diff --git a/MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor @@ -26,12 +26,12 @@ else } foreach (var s in PolicyRoomList) { - <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">@s.Name</a> + <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">[@s.Shortcode] @s.Name (@s.RoomId)</a> <br/> } - <div style="margin-bottom: 4em;"></div> } +<div style="margin-bottom: 4em;"></div> <LogView></LogView> @code { @@ -47,9 +47,9 @@ else protected override async Task OnInitializedAsync() { - if (!RuntimeStorage.WasLoaded) await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + if (!LocalStorageWrapper.WasLoaded) await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeStorage.AccessToken == null || RuntimeStorage.CurrentHomeserver == null) + if (LocalStorageWrapper.AccessToken == null || LocalStorageWrapper.CurrentHomeserver == null) { NavigationManager.NavigateTo("/Login"); return; @@ -60,13 +60,31 @@ else private async Task EnumeratePolicyRooms() { + var xxxrooms = await LocalStorageWrapper.CurrentHomeServer.GetJoinedRooms(); + totalRoomCount = xxxrooms.Count; + StateHasChanged(); + + var xxxsemaphore = new SemaphoreSlim(256); + var xxxtasks = new List<Task<PolicyRoomInfo?>>(); + foreach (var room in xxxrooms) + { + xxxtasks.Add(GetPolicyRoomInfo(room.RoomId, xxxsemaphore)); + } + var xxxresults = await Task.WhenAll(xxxtasks); + PolicyRoomList.AddRange(xxxresults.Where(x => x != null).Select(x => x.Value)); + + Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}"); + return; + using HttpClient wc = new(); - wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); + wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + + //get room list //temporary hack until rooms get enumerated... string[] rooms = { "!fTjMjIzNKEsFlUIiru:neko.dev" }; - var _rooms = await wc.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/v3/joined_rooms"); + var _rooms = await wc.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/joined_rooms"); Console.WriteLine($"Got {_rooms.StatusCode}..."); if (!_rooms.IsSuccessStatusCode) { @@ -82,15 +100,15 @@ else totalRoomCount = rooms.Length; StateHasChanged(); - var semaphore = new SemaphoreSlim(128); + var semaphore = new SemaphoreSlim(256); var tasks = new List<Task<PolicyRoomInfo?>>(); foreach (string room in rooms) { tasks.Add(GetPolicyRoomInfo(room, semaphore)); } var results = await Task.WhenAll(tasks); - PolicyRoomList.AddRange(results.Where(x => x != null).Select(x=>x.Value)); - + PolicyRoomList.AddRange(results.Where(x => x != null).Select(x => x.Value)); + //print to console Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}"); @@ -101,16 +119,40 @@ else try { await semaphore.WaitAsync(); + PolicyRoomInfo roomInfo = new() + { + RoomId = room + }; using HttpClient wc = new(); - wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); - var sk = await wc.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/v3/rooms/{room}/state/org.matrix.mjolnir.shortcode"); + wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + var sk = await wc.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/rooms/{room}/state/org.matrix.mjolnir.shortcode"); if (sk.IsSuccessStatusCode) { var sko = await sk.Content.ReadFromJsonAsync<JsonElement>(); if (sko.TryGetProperty("shortcode", out JsonElement shortcode)) { Console.WriteLine($"Room {room} has a shortcode: {shortcode.GetString()}!"); - return new PolicyRoomInfo() { Name = room, Shortcode = shortcode.GetString(), RoomId = room }; + roomInfo.Shortcode = shortcode.GetString(); + // sk = await wc.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/rooms/{room}/state/m.room.name"); + // if (sk.IsSuccessStatusCode) + // { + // Console.WriteLine($"Got content: {await sk.Content.ReadAsStringAsync()}"); + // sko = await sk.Content.ReadFromJsonAsync<JsonElement>(); + // if (sko.TryGetProperty("name", out JsonElement roomname)) + // { + // Console.WriteLine($"Room {room} has a name: {roomname.GetString()}!"); + // roomInfo.Name = roomname.GetString(); + // } + // else Console.WriteLine("No record found..."); + // } + // else if (sk.StatusCode == System.Net.HttpStatusCode.NotFound) + // { + // } + // else Console.WriteLine($"Got failure while checking {room}: {sk.StatusCode} ({await sk.Content.ReadAsStringAsync()})..."); + var r = await LocalStorageWrapper.CurrentHomeServer.GetRoom(room); + roomInfo.Shortcode = (await r.GetStateAsync("org.matrix.mjolnir.shortcode")).Value.GetProperty("shortcode").GetString(); + roomInfo.Name = await r.GetNameAsync(); + return roomInfo; } else Console.WriteLine("No record found..."); } @@ -118,6 +160,7 @@ else { } else Console.WriteLine($"Got failure while checking {room}: {sk.StatusCode} ({await sk.Content.ReadAsStringAsync()})..."); + return null; } finally @@ -127,11 +170,11 @@ else semaphore.Release(); } } - + public struct PolicyRoomInfo { public string RoomId { get; set; } - public string Shortcode { get; set; } - public string Name { get; set; } + public string? Shortcode { get; set; } + public string? Name { get; set; } } -} -\ No newline at end of file + } +\ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomStateEditorPage.razor b/MatrixRoomUtils.Web/Pages/RoomStateEditorPage.razor @@ -0,0 +1,177 @@ +@page "/RoomStateViewer/{RoomId}/Edit" +@using MatrixRoomUtils.Authentication +@using MatrixRoomUtils.Web.Classes +@using Blazored.LocalStorage +@using System.Net.Http.Headers +@using System.Text.Json +@using System.Xml.Schema +@using MatrixRoomUtils.Extensions +@using MatrixRoomUtils.StateEventTypes +@using MatrixRoomUtils.Web.Shared.IndexComponents +@using Microsoft.Win32.SafeHandles +@inject ILocalStorageService LocalStorage +@inject NavigationManager NavigationManager +<h3>Room state editor</h3> +<p>Room ID: @RoomId</p> + +<p>@status</p> + +<input type="checkbox" id="showAll" @bind="ShowMembershipEvents"/> Show member events +<br/> +<InputSelect @bind-Value="shownStateKey"> + <option value="">-- State key --</option> + @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key != "").Select(x => x.state_key).Distinct().OrderBy(x => x)) + { + <option value="@stateEvent">@stateEvent</option> + Console.WriteLine(stateEvent); + } +</InputSelect> +<br/> +<InputSelect @bind-Value="shownType"> + <option value="">-- Type --</option> + @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key != shownStateKey).Select(x => x.type).Distinct().OrderBy(x => x)) + { + <option value="@stateEvent">@stateEvent</option> + } +</InputSelect> +<br/> + +<textarea @bind="shownEventJson" style="width: 100%; height: fit-content;"></textarea> + +<LogView></LogView> + +@code { + //get room list + // - sync withroom list filter + // type = support.feline.msc3784 + //support.feline.policy.lists.msc.v1 + + [Parameter] + public string? RoomId { get; set; } + + public List<StateEvent> FilteredEvents { get; set; } = new(); + public List<StateEvent> Events { get; set; } = new(); + public string status = ""; + + protected override async Task OnInitializedAsync() + { + if (!LocalStorageWrapper.WasLoaded) await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + await base.OnInitializedAsync(); + if (LocalStorageWrapper.AccessToken == null || LocalStorageWrapper.CurrentHomeserver == null) + { + NavigationManager.NavigateTo("/Login"); + return; + } + RoomId = RoomId.Replace('~', '.'); + await LoadStatesAsync(); + Console.WriteLine("Policy list editor initialized!"); + } + + private DateTime _lastUpdate = DateTime.Now; + + private async Task LoadStatesAsync() + { + int StateLoaded = 0; + using var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); + // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json"); + //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>(); + var _data = await response.Content.ReadAsStreamAsync(); + var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEvent>(_data); + await foreach (var _ev in __events) + { + var e = new StateEvent() + { + type = _ev.type, + state_key = _ev.state_key, + origin_server_ts = _ev.origin_server_ts, + content = _ev.content + }; + Events.Add(e); + if (string.IsNullOrEmpty(e.state_key)) + { + FilteredEvents.Add(e); + } + StateLoaded++; + if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) + { + _lastUpdate = DateTime.Now; + status = $"Loaded {StateLoaded} state events"; + StateHasChanged(); + await Task.Delay(0); + } + } + + StateHasChanged(); + } + + private async Task RebuildFilteredData() + { + status = "Rebuilding filtered data..."; + StateHasChanged(); + await Task.Delay(1); + var _FilteredEvents = Events; + if (!ShowMembershipEvents) + _FilteredEvents = _FilteredEvents.Where(x => x.type != "m.room.member").ToList(); + + status = "Done, rerendering!"; + StateHasChanged(); + await Task.Delay(1); + FilteredEvents = _FilteredEvents; + + if(_shownType != null) + shownEventJson = _FilteredEvents.Where(x => x.type == _shownType).First().content.ToJson(indent: true, ignoreNull: true); + + StateHasChanged(); + } + + + public struct PreRenderedStateEvent + { + public string content { get; set; } + public long origin_server_ts { get; set; } + public string state_key { get; set; } + public string type { get; set; } + // public string sender { get; set; } + // public string event_id { get; set; } + // public string user_id { get; set; } + // public string replaces_state { get; set; } + } + + public bool ShowMembershipEvents + { + get => _showMembershipEvents; + set + { + _showMembershipEvents = value; + RebuildFilteredData(); + } + } + + private bool _showMembershipEvents; + private string _shownStateKey; + private string _shownType; + + private string shownStateKey + { + get => _shownStateKey; + set + { + _shownStateKey = value; + RebuildFilteredData(); + } + } + + private string shownType + { + get => _shownType; + set + { + _shownType = value; + RebuildFilteredData(); + } + } + + private string shownEventJson { get; set; } +} +\ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomStateRoomList.razor b/MatrixRoomUtils.Web/Pages/RoomStateRoomList.razor @@ -9,7 +9,7 @@ @using MatrixRoomUtils.StateEventTypes @inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager -<h3>Policy list editor</h3> +<h3>Room state viewer</h3> <h5>Room list</h5> <hr/> @@ -26,7 +26,7 @@ else } foreach (var s in PolicyRoomList) { - <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">@s.Name</a> + <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">@s.Name (@s.RoomId)</a> <br/> } <div style="margin-bottom: 4em;"></div> @@ -43,9 +43,9 @@ else protected override async Task OnInitializedAsync() { - if (!RuntimeStorage.WasLoaded) await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + if (!LocalStorageWrapper.WasLoaded) await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeStorage.AccessToken == null || RuntimeStorage.CurrentHomeserver == null) + if (LocalStorageWrapper.AccessToken == null || LocalStorageWrapper.CurrentHomeserver == null) { NavigationManager.NavigateTo("/Login"); return; @@ -57,12 +57,12 @@ else private async Task EnumeratePolicyRooms() { using HttpClient wc = new(); - wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); + wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); //get room list //temporary hack until rooms get enumerated... string[] rooms = { "!fTjMjIzNKEsFlUIiru:neko.dev" }; - var _rooms = await wc.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/v3/joined_rooms"); + var _rooms = await wc.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/joined_rooms"); Console.WriteLine($"Got {_rooms.StatusCode}..."); if (!_rooms.IsSuccessStatusCode) { @@ -78,26 +78,59 @@ else totalRoomCount = rooms.Length; StateHasChanged(); - // var semaphore = new SemaphoreSlim(128); - // var tasks = new List<Task<PolicyRoomInfo?>>(); - // foreach (string room in rooms) - // { - // tasks.Add(GetPolicyRoomInfo(room, semaphore)); - // } - // var results = await Task.WhenAll(tasks); - // PolicyRoomList.AddRange(results.Where(x => x != null).Select(x=>x.Value)); - PolicyRoomList.AddRange(rooms.Select(x=>new PolicyRoomInfo() { Name = x, RoomId = x, Shortcode = "N/A" })); + var semaphore = new SemaphoreSlim(128); + var tasks = new List<Task<PolicyRoomInfo?>>(); + foreach (string room in rooms) + { + tasks.Add(GetPolicyRoomInfo(room, semaphore)); + } + var results = await Task.WhenAll(tasks); + PolicyRoomList.AddRange(results.Where(x => x != null).Select(x=>x.Value)); + StateHasChanged(); + } - //print to console - Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}"); + private async Task<PolicyRoomInfo?> GetPolicyRoomInfo(string room, SemaphoreSlim semaphore) + { + try + { + await semaphore.WaitAsync(); + var roomInfo = new PolicyRoomInfo() + { + RoomId = room + }; + using HttpClient wc = new(); + wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + var sk = await wc.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/rooms/{room}/state/m.room.name"); + if (sk.IsSuccessStatusCode) + { + Console.WriteLine($"Got content: {await sk.Content.ReadAsStringAsync()}"); + var sko = await sk.Content.ReadFromJsonAsync<JsonElement>(); + if (sko.TryGetProperty("name", out JsonElement shortcode)) + { + Console.WriteLine($"Room {room} has a name: {shortcode.GetString()}!"); + roomInfo.Name = shortcode.GetString(); + } + else Console.WriteLine("No record found..."); + } + else if (sk.StatusCode == System.Net.HttpStatusCode.NotFound) + { + } + else Console.WriteLine($"Got failure while checking {room}: {sk.StatusCode} ({await sk.Content.ReadAsStringAsync()})..."); + return roomInfo; + } + finally + { + checkedRoomCount++; + StateHasChanged(); + semaphore.Release(); + } } - - + + public struct PolicyRoomInfo { public string RoomId { get; set; } - public string Shortcode { get; set; } public string Name { get; set; } } } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomStateViewerPage.razor b/MatrixRoomUtils.Web/Pages/RoomStateViewerPage.razor @@ -80,9 +80,9 @@ protected override async Task OnInitializedAsync() { - if (!RuntimeStorage.WasLoaded) await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + if (!LocalStorageWrapper.WasLoaded) await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeStorage.AccessToken == null || RuntimeStorage.CurrentHomeserver == null) + if (LocalStorageWrapper.AccessToken == null || LocalStorageWrapper.CurrentHomeserver == null) { NavigationManager.NavigateTo("/Login"); return; @@ -97,8 +97,8 @@ { int StateLoaded = 0; using var client = new HttpClient(); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); - var response = await client.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json"); //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>(); var _data = await response.Content.ReadAsStreamAsync(); diff --git a/MatrixRoomUtils.Web/Pages/UserImportPage.razor b/MatrixRoomUtils.Web/Pages/UserImportPage.razor @@ -15,7 +15,7 @@ <table border="1"> @foreach (var (homeserver, username, password) in records) { - <tr style="background-color: @(RuntimeStorage.UsersCache.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}") ? "green" : "unset")"> + <tr style="background-color: @(LocalStorageWrapper.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}") ? "green" : "unset")"> <td style="border-width: 1px;">@username</td> <td style="border-width: 1px;">@homeserver</td> <td style="border-width: 1px;">@password.Length chars</td> @@ -33,23 +33,21 @@ { foreach (var (homeserver, username, password) in records) { - if(RuntimeStorage.UsersCache.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}")) continue; - var result = await MatrixAccount.Login(homeserver, username, password); + if(LocalStorageWrapper.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}")) continue; + var result = await MatrixAuth.Login(homeserver, username, password); Console.WriteLine($"Obtained access token for {result.UserId}!"); - RuntimeStorage.AccessToken = result.AccessToken; - var userinfo = new UserInfo() { LoginResponse = result }; - userinfo.Profile = await MatrixAccount.GetProfile(result.HomeServer, result.UserId); + userinfo.Profile = await MatrixAuth.GetProfile(result.HomeServer, result.UserId); - RuntimeStorage.UsersCache.Add(result.AccessToken, userinfo); + LocalStorageWrapper.LoginSessions.Add(result.AccessToken, userinfo); StateHasChanged(); } - await RuntimeStorage.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); } private async Task FileChanged(InputFileChangeEventArgs obj) diff --git a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor @@ -9,7 +9,7 @@ <div style="margin-bottom: 1em;"> <img style="border-radius: 50%; height: 3em; width: 3em;" src="@_avatarUrl"/> - <span style="margin-left: 1em;"><input type="radio" name="csa" checked="@(RuntimeStorage.AccessToken == Token)" onclick="@SetCurrent" style="text-decoration-line: unset;"/> <b>@User.Profile.DisplayName</b> on <b>@User.LoginResponse.HomeServer</b></span> + <span style="margin-left: 1em;"><input type="radio" name="csa" checked="@(LocalStorageWrapper.AccessToken == Token)" onclick="@SetCurrent" style="text-decoration-line: unset;"/> <b>@User.Profile.DisplayName</b> on <b>@User.LoginResponse.HomeServer</b></span> <a href="#" onclick="@RemoveUser">Remove</a> </div> @@ -32,17 +32,18 @@ private async Task RemoveUser() { - RuntimeStorage.UsersCache.Remove(Token); - await RuntimeStorage.SaveToLocalStorage(LocalStorage); + LocalStorageWrapper.LoginSessions.Remove(Token); + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); _removed = true; StateHasChanged(); } private async Task SetCurrent() { - RuntimeStorage.AccessToken = Token; - RuntimeStorage.CurrentHomeserver = await MatrixAccount.ResolveHomeserverFromWellKnown(RuntimeStorage.UsersCache[Token].LoginResponse.HomeServer); - await RuntimeStorage.SaveToLocalStorage(LocalStorage); + LocalStorageWrapper.AccessToken = Token; + LocalStorageWrapper.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(LocalStorageWrapper.LoginSessions[Token].LoginResponse.HomeServer); + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); StateHasChanged(); } diff --git a/MatrixRoomUtils.Web/Shared/MainLayout.razor b/MatrixRoomUtils.Web/Shared/MainLayout.razor @@ -25,9 +25,9 @@ protected override async Task OnInitializedAsync() { - if (!RuntimeStorage.WasLoaded) + if (!LocalStorageWrapper.WasLoaded) { - await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); Console.WriteLine("Loaded from local storage"); StateHasChanged(); }