IHomeServer.cs (5255B)
1 using System.Net.Http.Json; 2 using System.Text.Json; 3 using MatrixRoomUtils.Core.Extensions; 4 using MatrixRoomUtils.Core.Responses; 5 6 namespace MatrixRoomUtils.Core.Interfaces; 7 8 public class IHomeServer 9 { 10 private Dictionary<string, ProfileResponse?> _profileCache = new(); 11 public string HomeServerDomain { get; set; } 12 public string FullHomeServerDomain { get; set; } 13 14 private protected HttpClient _httpClient { get; set; } = new(); 15 16 public async Task<string> ResolveHomeserverFromWellKnown(string homeserver) 17 { 18 var res = await _resolveHomeserverFromWellKnown(homeserver); 19 if(!res.StartsWith("http")) res = "https://" + res; 20 if(res.EndsWith(":443")) res = res.Substring(0, res.Length - 4); 21 return res; 22 } 23 private async Task<string> _resolveHomeserverFromWellKnown(string homeserver) 24 { 25 if (RuntimeCache.HomeserverResolutionCache.Count == 0) 26 { 27 Console.WriteLine("No cached homeservers, resolving..."); 28 await Task.Delay(Random.Shared.Next(1000, 5000)); 29 } 30 if (RuntimeCache.HomeserverResolutionCache.ContainsKey(homeserver)) 31 { 32 if (RuntimeCache.HomeserverResolutionCache[homeserver].ResolutionTime < DateTime.Now.AddHours(1)) 33 { 34 Console.WriteLine($"Found cached homeserver: {RuntimeCache.HomeserverResolutionCache[homeserver].Result}"); 35 return RuntimeCache.HomeserverResolutionCache[homeserver].Result; 36 } 37 Console.WriteLine($"Cached homeserver expired, removing: {RuntimeCache.HomeserverResolutionCache[homeserver].Result}"); 38 RuntimeCache.HomeserverResolutionCache.Remove(homeserver); 39 } 40 //throw new NotImplementedException(); 41 42 string result = null; 43 Console.WriteLine($"Resolving homeserver: {homeserver}"); 44 if (!homeserver.StartsWith("http")) homeserver = "https://" + homeserver; 45 if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/client")) 46 { 47 Console.WriteLine($"Got successful response for client well-known..."); 48 var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/client"); 49 Console.WriteLine($"Response: {resp.ToString()}"); 50 var hs = resp.GetProperty("m.homeserver").GetProperty("base_url").GetString(); 51 result = hs; 52 } 53 else 54 { 55 Console.WriteLine($"No client well-known..."); 56 if (await _httpClient.CheckSuccessStatus($"{homeserver}/.well-known/matrix/server")) 57 { 58 var resp = await _httpClient.GetFromJsonAsync<JsonElement>($"{homeserver}/.well-known/matrix/server"); 59 var hs = resp.GetProperty("m.server").GetString(); 60 result = hs; 61 } 62 else 63 { 64 Console.WriteLine($"No server well-known..."); 65 if (await _httpClient.CheckSuccessStatus($"{homeserver}/_matrix/client/versions")) result = homeserver; 66 else 67 { 68 Console.WriteLine("No homeserver on shortname..."); 69 if (await _httpClient.CheckSuccessStatus($"{homeserver.Replace("//", "//matrix.")}/_matrix/client/versions")) result = homeserver.Replace("//", "//matrix."); 70 else Console.WriteLine($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); 71 } 72 } 73 } 74 75 if (result != null) 76 { 77 Console.WriteLine($"Resolved homeserver: {homeserver} -> {result}"); 78 RuntimeCache.HomeserverResolutionCache.TryAdd(homeserver, new() 79 { 80 Result = result, 81 ResolutionTime = DateTime.Now 82 }); 83 return result; 84 } 85 throw new InvalidDataException($"Failed to resolve homeserver, not on {homeserver}, nor do client or server well-knowns exist!"); 86 } 87 public async Task<ProfileResponse> GetProfile(string mxid, bool debounce = false, bool cache = true) 88 { 89 if (cache) 90 { 91 if(debounce) await Task.Delay(Random.Shared.Next(100, 500)); 92 if (_profileCache.ContainsKey(mxid)) 93 { 94 while (_profileCache[mxid] == null) 95 { 96 Console.WriteLine($"Waiting for profile cache for {mxid}, currently {_profileCache[mxid]?.ToJson() ?? "null"} within {_profileCache.Count} profiles..."); 97 await Task.Delay(Random.Shared.Next(50, 500)); 98 } 99 return _profileCache[mxid]; 100 } 101 } 102 103 _profileCache.Add(mxid, null); 104 var resp = await _httpClient.GetAsync($"/_matrix/client/r0/profile/{mxid}"); 105 var data = await resp.Content.ReadFromJsonAsync<JsonElement>(); 106 if(!resp.IsSuccessStatusCode) Console.WriteLine("Profile: " + data.ToString()); 107 var profile = data.Deserialize<ProfileResponse>(); 108 _profileCache[mxid] = profile; 109 return profile; 110 } 111 public string ResolveMediaUri(string mxc) 112 { 113 return mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/r0/download/"); 114 } 115 }