Partial User-Interactive Authentication, allow skipping homeserver typing
3 files changed, 103 insertions, 4 deletions
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index afa6a6c..267b54d 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -128,10 +128,20 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver {
public virtual async IAsyncEnumerable<GenericRoom> GetJoinedRoomsByType(string type) {
var rooms = await GetJoinedRooms();
var tasks = rooms.Select(async room => {
- var roomType = await room.GetRoomType();
- if (roomType == type) return room;
-
- return null;
+ while (true) {
+ try {
+ var roomType = await room.GetRoomType();
+ if (roomType == type) return room;
+ return null;
+ }
+ catch (MatrixException e) {
+ throw;
+ }
+ catch (Exception e) {
+ Console.WriteLine($"Failed to get room type for {room.RoomId}: {e.Message}");
+ await Task.Delay(1000);
+ }
+ }
}).ToAsyncEnumerable();
await foreach (var result in tasks)
diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs
index e6d58b1..c29137c 100644
--- a/LibMatrix/Homeservers/RemoteHomeServer.cs
+++ b/LibMatrix/Homeservers/RemoteHomeServer.cs
@@ -1,5 +1,6 @@
using System.Net.Http.Json;
using System.Text.Json;
+using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using System.Web;
using ArcaneLibs.Extensions;
@@ -24,6 +25,7 @@ public class RemoteHomeserver {
if (proxy is not null) ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", baseUrl);
if (!string.IsNullOrWhiteSpace(wellKnownUris.Server))
FederationClient = new FederationClient(WellKnownUris.Server!, proxy);
+ Auth = new(this);
}
private Dictionary<string, object> _profileCache { get; set; } = new();
@@ -106,6 +108,8 @@ public class RemoteHomeserver {
if (mxcUri.StartsWith("https://")) return mxcUri;
return $"{ClientHttpClient.BaseAddress}/_matrix/media/v3/download/{mxcUri.Replace("mxc://", "")}".Replace("//_matrix", "/_matrix");
}
+
+ public UserInteractiveAuthClient Auth;
}
public class AliasResult {
diff --git a/LibMatrix/Homeservers/UserInteractiveAuthClient.cs b/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
new file mode 100644
index 0000000..8be2cb9
--- /dev/null
+++ b/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
@@ -0,0 +1,85 @@
+using System.Net.Http.Json;
+using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
+using ArcaneLibs.Extensions;
+using LibMatrix.Responses;
+
+namespace LibMatrix.Homeservers;
+
+public class UserInteractiveAuthClient {
+ public UserInteractiveAuthClient(RemoteHomeserver hs) {
+ Homeserver = hs;
+ }
+
+ [JsonIgnore]
+ public RemoteHomeserver Homeserver { get; }
+ private LoginResponse? _guestLogin;
+
+ public async Task<UIAStage1Client> GetAvailableFlowsAsync(bool enableRegister = false, bool enableGuest = false) {
+ // var resp = await Homeserver.ClientHttpClient.GetAsync("/_matrix/client/v3/login");
+ // var data = await resp.Content.ReadFromJsonAsync<LoginFlowsResponse>();
+ // if (!resp.IsSuccessStatusCode) Console.WriteLine("LoginFlows: " + await resp.Content.ReadAsStringAsync());
+ // var loginFlows = data;
+ //
+ // try {
+ // var req = new HttpRequestMessage(HttpMethod.Post, "/_matrix/client/v3/register") {
+ // Content = new StringContent("{}")
+ // };
+ // var resp2 = await Homeserver.ClientHttpClient.SendUnhandledAsync(req, CancellationToken.None);
+ // var data2 = await resp2.Content.ReadFromJsonAsync<RegisterFlowsResponse>();
+ // if (!resp.IsSuccessStatusCode) Console.WriteLine("RegisterFlows: " + data2.ToJson());
+ // // return data;
+ // }
+ // catch (MatrixException e) {
+ // if (e is { ErrorCode: "M_FORBIDDEN" }) return null;
+ // throw;
+ // }
+ // catch (Exception e) {
+ // Console.WriteLine(e);
+ // throw;
+ // }
+ //
+ //
+ return new UIAStage1Client() {
+
+ };
+ }
+
+ private async Task<RegisterFlowsResponse?> GetRegisterFlowsAsync() {
+ return null;
+ }
+
+ internal class RegisterFlowsResponse {
+ [JsonPropertyName("session")]
+ public string Session { get; set; } = null!;
+
+ [JsonPropertyName("flows")]
+ public List<RegisterFlow> Flows { get; set; } = null!;
+
+ [JsonPropertyName("params")]
+ public JsonObject Params { get; set; } = null!;
+
+ public class RegisterFlow {
+ [JsonPropertyName("stages")]
+ public List<string> Stages { get; set; } = null!;
+ }
+ }
+
+ internal class LoginFlowsResponse {
+ [JsonPropertyName("flows")]
+ public List<LoginFlow> Flows { get; set; } = null!;
+
+ public class LoginFlow {
+ [JsonPropertyName("type")]
+ public string Type { get; set; } = null!;
+ }
+ }
+
+ public interface IUIAStage {
+ public IUIAStage? PreviousStage { get; }
+ }
+ public class UIAStage1Client : IUIAStage {
+ public IUIAStage? PreviousStage { get; }
+ // public LoginFlowsResponse LoginFlows { get; set; }
+ }
+}
\ No newline at end of file
|