Room.cs (5901B)
1 using System.Diagnostics.CodeAnalysis; 2 using System.Net.Http.Json; 3 using System.Reflection; 4 using System.Text.Json; 5 using System.Text.Json.Serialization; 6 using System.Web; 7 using MatrixRoomUtils.Core.Extensions; 8 9 namespace MatrixRoomUtils.Core; 10 11 public class Room 12 { 13 private readonly HttpClient _httpClient; 14 public string RoomId { get; set; } 15 16 public Room(HttpClient httpClient, string roomId) 17 { 18 _httpClient = httpClient; 19 RoomId = roomId; 20 } 21 22 public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "", bool logOnFailure = true) 23 { 24 var url = $"/_matrix/client/v3/rooms/{RoomId}/state"; 25 if (!string.IsNullOrEmpty(type)) url += $"/{type}"; 26 if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}"; 27 28 var res = await _httpClient.GetAsync(url); 29 if (!res.IsSuccessStatusCode) 30 { 31 if (logOnFailure) Console.WriteLine($"{RoomId}/{stateKey}/{type} - got status: {res.StatusCode}"); 32 return null; 33 } 34 35 var result = await res.Content.ReadFromJsonAsync<JsonElement>(); 36 return result; 37 } 38 39 public async Task<T?> GetStateAsync<T>(string type, string stateKey = "", bool logOnFailure = false) 40 { 41 var res = await GetStateAsync(type, stateKey, logOnFailure); 42 if (res == null) return default; 43 return res.Value.Deserialize<T>(); 44 } 45 46 public async Task<string> GetNameAsync() 47 { 48 var res = await GetStateAsync("m.room.name"); 49 if (!res.HasValue) 50 { 51 Console.WriteLine($"Room {RoomId} has no name!"); 52 return RoomId; 53 } 54 55 var resn = res?.TryGetProperty("name", out var name) ?? false ? name.GetString() ?? RoomId : RoomId; 56 //Console.WriteLine($"Got name: {resn}"); 57 return resn; 58 } 59 60 public async Task JoinAsync(string[]? homeservers = null) 61 { 62 string join_url = $"/_matrix/client/r0/join/{HttpUtility.UrlEncode(RoomId)}"; 63 Console.WriteLine($"Calling {join_url} with {homeservers?.Length ?? 0} via's..."); 64 if (homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] }; 65 var fullJoinUrl = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers); 66 var res = await _httpClient.PostAsync(fullJoinUrl, null); 67 } 68 69 public async Task<List<string>> GetMembersAsync(bool joinedOnly = true) 70 { 71 var res = await GetStateAsync(""); 72 if (!res.HasValue) return new List<string>(); 73 var members = new List<string>(); 74 foreach (var member in res.Value.EnumerateArray()) 75 { 76 if (member.GetProperty("type").GetString() != "m.room.member") continue; 77 if (joinedOnly && member.GetProperty("content").GetProperty("membership").GetString() != "join") continue; 78 var memberId = member.GetProperty("state_key").GetString(); 79 members.Add(memberId ?? throw new InvalidOperationException("Event type was member but state key was null!")); 80 } 81 82 return members; 83 } 84 85 public async Task<List<string>> GetAliasesAsync() 86 { 87 var res = await GetStateAsync("m.room.aliases"); 88 if (!res.HasValue) return new List<string>(); 89 var aliases = new List<string>(); 90 foreach (var alias in res.Value.GetProperty("aliases").EnumerateArray()) 91 { 92 aliases.Add(alias.GetString() ?? ""); 93 } 94 95 return aliases; 96 } 97 98 public async Task<string> GetCanonicalAliasAsync() 99 { 100 var res = await GetStateAsync("m.room.canonical_alias"); 101 if (!res.HasValue) return ""; 102 return res.Value.GetProperty("alias").GetString() ?? ""; 103 } 104 105 public async Task<string> GetTopicAsync() 106 { 107 var res = await GetStateAsync("m.room.topic"); 108 if (!res.HasValue) return ""; 109 return res.Value.GetProperty("topic").GetString() ?? ""; 110 } 111 112 public async Task<string> GetAvatarUrlAsync() 113 { 114 var res = await GetStateAsync("m.room.avatar"); 115 if (!res.HasValue) return ""; 116 return res.Value.GetProperty("url").GetString() ?? ""; 117 } 118 119 public async Task<JoinRules> GetJoinRuleAsync() 120 { 121 var res = await GetStateAsync("m.room.join_rules"); 122 if (!res.HasValue) return new JoinRules(); 123 return res.Value.Deserialize<JoinRules>() ?? new JoinRules(); 124 } 125 126 public async Task<string> GetHistoryVisibilityAsync() 127 { 128 var res = await GetStateAsync("m.room.history_visibility"); 129 if (!res.HasValue) return ""; 130 return res.Value.GetProperty("history_visibility").GetString() ?? ""; 131 } 132 133 public async Task<string> GetGuestAccessAsync() 134 { 135 var res = await GetStateAsync("m.room.guest_access"); 136 if (!res.HasValue) return ""; 137 return res.Value.GetProperty("guest_access").GetString() ?? ""; 138 } 139 140 public async Task<CreateEvent> GetCreateEventAsync() 141 { 142 var res = await GetStateAsync("m.room.create"); 143 if (!res.HasValue) return new CreateEvent(); 144 145 res.FindExtraJsonFields(typeof(CreateEvent)); 146 147 return res.Value.Deserialize<CreateEvent>() ?? new CreateEvent(); 148 } 149 } 150 151 public class CreateEvent 152 { 153 [JsonPropertyName("creator")] public string Creator { get; set; } 154 [JsonPropertyName("room_version")] public string RoomVersion { get; set; } 155 [JsonPropertyName("type")] public string? Type { get; set; } 156 [JsonPropertyName("predecessor")] public object? Predecessor { get; set; } 157 [JsonPropertyName("m.federate")] public bool Federate { get; set; } 158 } 159 160 public class JoinRules 161 { 162 private const string Public = "public"; 163 private const string Invite = "invite"; 164 private const string Knock = "knock"; 165 166 [JsonPropertyName("join_rule")] public string JoinRule { get; set; } 167 [JsonPropertyName("allow")] public List<string> Allow { get; set; } 168 }