about summary refs log tree commit diff
path: root/LibMatrix/Homeservers
diff options
context:
space:
mode:
Diffstat (limited to 'LibMatrix/Homeservers')
-rw-r--r--LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs61
-rw-r--r--LibMatrix/Homeservers/FederationClient.cs4
-rw-r--r--LibMatrix/Homeservers/RemoteHomeServer.cs14
-rw-r--r--LibMatrix/Homeservers/UserInteractiveAuthClient.cs12
4 files changed, 51 insertions, 40 deletions
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs

index f47ab64..8c95bc3 100644 --- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs +++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -39,11 +39,12 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { public string UserId => WhoAmI.UserId; public string UserLocalpart => UserId.Split(":")[0][1..]; public string ServerName => UserId.Split(":", 2)[1]; + public string BaseUrl => ClientHttpClient.BaseAddress!.ToString().TrimEnd('/'); [JsonIgnore] public string AccessToken { get; set; } - public HsNamedCaches NamedCaches { get; set; } = null!; + public HsNamedCaches NamedCaches { get; set; } public GenericRoom GetRoom(string roomId) { if (roomId is null || !roomId.StartsWith("!")) throw new ArgumentException("Room ID must start with !", nameof(roomId)); @@ -408,22 +409,22 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { #region Authenticated Media // TODO: implement /_matrix/client/v1/media/config when it's actually useful - https://spec.matrix.org/v1.11/client-server-api/#get_matrixclientv1mediaconfig + private bool? _serverSupportsAuthMedia; - private (string ServerName, string MediaId) ParseMxcUri(string mxcUri) { - if (!mxcUri.StartsWith("mxc://")) throw new ArgumentException("Matrix Content URIs must start with 'mxc://'", nameof(mxcUri)); - var parts = mxcUri[6..].Split('/'); - if (parts.Length != 2) throw new ArgumentException($"Invalid Matrix Content URI '{mxcUri}' passed! Matrix Content URIs must exist of only 2 parts!", nameof(mxcUri)); - return (parts[0], parts[1]); - } + public async Task<string> GetMediaUrlAsync(MxcUri mxcUri, string? filename = null, int? timeout = null) { + if (_serverSupportsAuthMedia == true) return mxcUri.ToDownloadUri(BaseUrl, filename, timeout); + if (_serverSupportsAuthMedia == false) return mxcUri.ToLegacyDownloadUri(BaseUrl, filename, timeout); - public async Task<Stream> GetMediaStreamAsync(string mxcUri, string? filename = null, int? timeout = null) { - var (serverName, mediaId) = ParseMxcUri(mxcUri); try { - var uri = $"/_matrix/client/v1/media/download/{serverName}/{mediaId}"; - if (!string.IsNullOrWhiteSpace(filename)) uri += $"/{HttpUtility.UrlEncode(filename)}"; - if (timeout is not null) uri += $"?timeout_ms={timeout}"; - var res = await ClientHttpClient.GetAsync(uri); - return await res.Content.ReadAsStreamAsync(); + // Console.WriteLine($"Trying authenticated media URL: {uri}"); + var res = await ClientHttpClient.SendAsync(new() { + Method = HttpMethod.Head, + RequestUri = (new Uri(mxcUri.ToDownloadUri(BaseUrl, filename, timeout), string.IsNullOrWhiteSpace(BaseUrl) ? UriKind.Relative : UriKind.Absolute)) + }); + if (res.IsSuccessStatusCode) { + _serverSupportsAuthMedia = true; + return mxcUri.ToDownloadUri(BaseUrl, filename, timeout); + } } catch (MatrixException e) { if (e is not { ErrorCode: "M_UNKNOWN" }) throw; @@ -431,11 +432,15 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { //fallback to legacy media try { - var uri = $"/_matrix/media/v3/download/{serverName}/{mediaId}"; - if (!string.IsNullOrWhiteSpace(filename)) uri += $"/{HttpUtility.UrlEncode(filename)}"; - if (timeout is not null) uri += $"?timeout_ms={timeout}"; - var res = await ClientHttpClient.GetAsync(uri); - return await res.Content.ReadAsStreamAsync(); + // Console.WriteLine($"Trying legacy media URL: {uri}"); + var res = await ClientHttpClient.SendAsync(new() { + Method = HttpMethod.Head, + RequestUri = new(mxcUri.ToLegacyDownloadUri(BaseUrl, filename, timeout), string.IsNullOrWhiteSpace(BaseUrl) ? UriKind.Relative : UriKind.Absolute) + }); + if (res.IsSuccessStatusCode) { + _serverSupportsAuthMedia = false; + return mxcUri.ToLegacyDownloadUri(BaseUrl, filename, timeout); + } } catch (MatrixException e) { if (e is not { ErrorCode: "M_UNKNOWN" }) throw; @@ -443,13 +448,19 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { throw new LibMatrixException() { ErrorCode = LibMatrixException.ErrorCodes.M_UNSUPPORTED, - Error = "Failed to download media" + Error = "Failed to get media URL" }; - // return default; } - public async Task<Stream> GetThumbnailStreamAsync(string mxcUri, int width, int height, string? method = null, int? timeout = null) { - var (serverName, mediaId) = ParseMxcUri(mxcUri); + public async Task<Stream> GetMediaStreamAsync(string mxcUri, string? filename = null, int? timeout = null) { + var uri = await GetMediaUrlAsync(mxcUri, filename, timeout); + var res = await ClientHttpClient.GetAsync(uri); + return await res.Content.ReadAsStreamAsync(); + } + + public async Task<Stream> GetThumbnailStreamAsync(MxcUri mxcUri, int width, int height, string? method = null, int? timeout = null) { + var (serverName, mediaId) = mxcUri; + try { var uri = new Uri($"/_matrix/client/v1/thumbnail/{serverName}/{mediaId}"); uri = uri.AddQuery("width", width.ToString()); @@ -494,7 +505,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { catch (MatrixException e) { if (e is not { ErrorCode: "M_UNRECOGNIZED" }) throw; } - + //fallback to legacy media try { var res = await ClientHttpClient.GetAsync($"/_matrix/media/v3/preview_url?url={HttpUtility.UrlEncode(url)}"); @@ -503,7 +514,7 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeserver { catch (MatrixException e) { if (e is not { ErrorCode: "M_UNRECOGNIZED" }) throw; } - + throw new LibMatrixException() { ErrorCode = LibMatrixException.ErrorCodes.M_UNSUPPORTED, Error = "Failed to download URL preview" diff --git a/LibMatrix/Homeservers/FederationClient.cs b/LibMatrix/Homeservers/FederationClient.cs
index c7f0240..617b737 100644 --- a/LibMatrix/Homeservers/FederationClient.cs +++ b/LibMatrix/Homeservers/FederationClient.cs
@@ -13,8 +13,8 @@ public class FederationClient { if (proxy is not null) HttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", federationEndpoint); } - public MatrixHttpClient HttpClient { get; set; } = null!; - public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } = null!; + public MatrixHttpClient HttpClient { get; set; } + public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } public async Task<ServerVersionResponse> GetServerVersionAsync() => await HttpClient.GetFromJsonAsync<ServerVersionResponse>("/_matrix/federation/v1/version"); } diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs
index 7995f03..7ac54a7 100644 --- a/LibMatrix/Homeservers/RemoteHomeServer.cs +++ b/LibMatrix/Homeservers/RemoteHomeServer.cs
@@ -10,24 +10,24 @@ using LibMatrix.Services; namespace LibMatrix.Homeservers; public class RemoteHomeserver { - public RemoteHomeserver(string baseUrl, HomeserverResolverService.WellKnownUris wellKnownUris, string? proxy) { + public RemoteHomeserver(string serverName, HomeserverResolverService.WellKnownUris wellKnownUris, string? proxy) { if (string.IsNullOrWhiteSpace(proxy)) proxy = null; - BaseUrl = baseUrl; + ServerNameOrUrl = serverName; WellKnownUris = wellKnownUris; ClientHttpClient = new MatrixHttpClient { - BaseAddress = new Uri(proxy?.TrimEnd('/') ?? wellKnownUris.Client?.TrimEnd('/') ?? throw new InvalidOperationException($"No client URI for {baseUrl}!")), + BaseAddress = new Uri(proxy?.TrimEnd('/') ?? wellKnownUris.Client?.TrimEnd('/') ?? throw new InvalidOperationException($"No client URI for {serverName}!")), // Timeout = TimeSpan.FromSeconds(300) // TODO: Re-implement this }; - if (proxy is not null) ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", baseUrl); + if (proxy is not null) ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", serverName); if (!string.IsNullOrWhiteSpace(wellKnownUris.Server)) FederationClient = new FederationClient(WellKnownUris.Server!, proxy); Auth = new(this); } private Dictionary<string, object> _profileCache { get; set; } = new(); - public string BaseUrl { get; } + public string ServerNameOrUrl { get; } [JsonIgnore] public MatrixHttpClient ClientHttpClient { get; set; } @@ -111,8 +111,8 @@ public class RemoteHomeserver { public class AliasResult { [JsonPropertyName("room_id")] - public string RoomId { get; set; } = null!; + public string RoomId { get; set; } [JsonPropertyName("servers")] - public List<string> Servers { get; set; } = null!; + public List<string> Servers { get; set; } } \ No newline at end of file diff --git a/LibMatrix/Homeservers/UserInteractiveAuthClient.cs b/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
index bb3889f..8de01d2 100644 --- a/LibMatrix/Homeservers/UserInteractiveAuthClient.cs +++ b/LibMatrix/Homeservers/UserInteractiveAuthClient.cs
@@ -49,27 +49,27 @@ public class UserInteractiveAuthClient { internal class RegisterFlowsResponse { [JsonPropertyName("session")] - public string Session { get; set; } = null!; + public string Session { get; set; } [JsonPropertyName("flows")] - public List<RegisterFlow> Flows { get; set; } = null!; + public List<RegisterFlow> Flows { get; set; } [JsonPropertyName("params")] - public JsonObject Params { get; set; } = null!; + public JsonObject Params { get; set; } public class RegisterFlow { [JsonPropertyName("stages")] - public List<string> Stages { get; set; } = null!; + public List<string> Stages { get; set; } } } internal class LoginFlowsResponse { [JsonPropertyName("flows")] - public List<LoginFlow> Flows { get; set; } = null!; + public List<LoginFlow> Flows { get; set; } public class LoginFlow { [JsonPropertyName("type")] - public string Type { get; set; } = null!; + public string Type { get; set; } } }