diff --git a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
new file mode 100644
index 0000000..dd9aa25
--- /dev/null
+++ 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/MatrixAuth.cs
index 4180df5..687ea07 100644
--- a/MatrixRoomUtils.Core/Authentication/MatrixAccount.cs
+++ b/MatrixRoomUtils.Core/Authentication/MatrixAuth.cs
@@ -4,7 +4,7 @@ using MatrixRoomUtils.Responses;
namespace MatrixRoomUtils.Authentication;
-public class MatrixAccount
+public class MatrixAuth
{
public static async Task<LoginResponse> Login(string homeserver, string username, string password)
{
@@ -43,13 +43,14 @@ public class MatrixAccount
{
Console.WriteLine($"Fetching profile for {mxid} on {homeserver}...");
homeserver = await ResolveHomeserverFromWellKnown(homeserver);
- var hc = new HttpClient();
+ 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();
diff --git a/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs b/MatrixRoomUtils.Core/Extensions/HttpClientExtensions.cs
new file mode 100644
index 0000000..66a5133
--- /dev/null
+++ 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
index e02f0b9..27d8265 100644
--- 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
new file mode 100644
index 0000000..84714f7
--- /dev/null
+++ 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
new file mode 100644
index 0000000..f4ad9c9
--- /dev/null
+++ 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
index eedc970..5a7514e 100644
--- 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
new file mode 100644
index 0000000..6cb439a
--- /dev/null
+++ 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
new file mode 100644
index 0000000..45262db
--- /dev/null
+++ 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; }
+}
|