From 0d0511e35d9965fc0ea5190ae3347c3d77c3334c Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Mon, 14 Aug 2023 04:09:13 +0200 Subject: Split LibMatrix into separate repo --- LibMatrix/RoomTypes/GenericRoom.cs | 186 +++++++++++++++++++++++++++++++++++++ LibMatrix/RoomTypes/SpaceRoom.cs | 25 +++++ 2 files changed, 211 insertions(+) create mode 100644 LibMatrix/RoomTypes/GenericRoom.cs create mode 100644 LibMatrix/RoomTypes/SpaceRoom.cs (limited to 'LibMatrix/RoomTypes') diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs new file mode 100644 index 0000000..b935b9d --- /dev/null +++ b/LibMatrix/RoomTypes/GenericRoom.cs @@ -0,0 +1,186 @@ +using System.Net.Http.Json; +using System.Text.Json; +using System.Web; +using LibMatrix.Extensions; +using LibMatrix.Responses; +using LibMatrix.StateEventTypes.Spec; + +namespace LibMatrix.RoomTypes; + +public class GenericRoom { + internal readonly AuthenticatedHomeServer _homeServer; + internal readonly MatrixHttpClient _httpClient; + + public GenericRoom(AuthenticatedHomeServer homeServer, string roomId) { + _homeServer = homeServer; + _httpClient = homeServer._httpClient; + RoomId = roomId; + if (GetType() != typeof(SpaceRoom)) + AsSpace = new SpaceRoom(homeServer, RoomId); + } + + public string RoomId { get; set; } + + [Obsolete("", true)] + public async Task GetStateAsync(string type, string stateKey = "") { + var url = $"/_matrix/client/v3/rooms/{RoomId}/state"; + if (!string.IsNullOrEmpty(type)) url += $"/{type}"; + if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}"; + return await _httpClient.GetFromJsonAsync(url); + } + + public async IAsyncEnumerable GetFullStateAsync() { + var res = await _httpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/state"); + var result = + JsonSerializer.DeserializeAsyncEnumerable(await res.Content.ReadAsStreamAsync()); + await foreach (var resp in result) { + yield return resp; + } + } + + public async Task GetStateAsync(string type, string stateKey = "") { + var url = $"/_matrix/client/v3/rooms/{RoomId}/state"; + if (!string.IsNullOrEmpty(type)) url += $"/{type}"; + if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}"; + try { +#if DEBUG && false + var resp = await _httpClient.GetFromJsonAsync(url); + try { + _homeServer._httpClient.PostAsJsonAsync( + "http://localhost:5116/validate/" + typeof(T).AssemblyQualifiedName, resp); + } + catch (Exception e) { + Console.WriteLine("[!!] Checking state response failed: " + e); + } + + return resp.Deserialize(); +#else + var resp = await _httpClient.GetFromJsonAsync(url); + return resp; +#endif + } + catch (MatrixException e) { + if (e is not { ErrorCode: "M_NOT_FOUND" }) { + throw; + } + + Console.WriteLine(e); + return default; + } + } + + public async Task GetMessagesAsync(string from = "", int limit = 10, string dir = "b", + string filter = "") { + var url = $"/_matrix/client/v3/rooms/{RoomId}/messages?from={from}&limit={limit}&dir={dir}"; + if (!string.IsNullOrEmpty(filter)) url += $"&filter={filter}"; + var res = await _httpClient.GetFromJsonAsync(url); + return res ?? new MessagesResponse(); + } + + public async Task GetNameAsync() { + try { + var res = await GetStateAsync("m.room.name"); + return res?.Name ?? RoomId; + } + catch (MatrixException e) { + return $"{RoomId} ({e.ErrorCode})"; + } + } + + public async Task JoinAsync(string[]? homeservers = null, string? reason = null) { + var join_url = $"/_matrix/client/v3/join/{HttpUtility.UrlEncode(RoomId)}"; + Console.WriteLine($"Calling {join_url} with {homeservers?.Length ?? 0} via's..."); + if (homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] }; + var fullJoinUrl = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers); + var res = await _httpClient.PostAsJsonAsync(fullJoinUrl, new { + reason + }); + } + + public async IAsyncEnumerable GetMembersAsync(bool joinedOnly = true) { + var res = GetFullStateAsync(); + await foreach (var member in res) { + if (member.Type != "m.room.member") continue; + if (joinedOnly && (member.TypedContent as RoomMemberEventData).Membership is not "join") continue; + yield return member; + } + } + + public async Task> GetAliasesAsync() { + var res = await GetStateAsync("m.room.aliases"); + return res.Aliases; + } + + public async Task GetCanonicalAliasAsync() => + await GetStateAsync("m.room.canonical_alias"); + + public async Task GetTopicAsync() => + await GetStateAsync("m.room.topic"); + + public async Task GetAvatarUrlAsync() => + await GetStateAsync("m.room.avatar"); + + public async Task GetJoinRuleAsync() => + await GetStateAsync("m.room.join_rules"); + + public async Task GetHistoryVisibilityAsync() => + await GetStateAsync("m.room.history_visibility"); + + public async Task GetGuestAccessAsync() => + await GetStateAsync("m.room.guest_access"); + + public async Task GetCreateEventAsync() => + await GetStateAsync("m.room.create"); + + public async Task GetRoomType() { + var res = await GetStateAsync("m.room.create"); + return res.Type; + } + + public async Task ForgetAsync() => + await _httpClient.PostAsync($"/_matrix/client/v3/rooms/{RoomId}/forget", null); + + public async Task LeaveAsync(string? reason = null) => + await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/leave", new { + reason + }); + + public async Task KickAsync(string userId, string? reason = null) => + await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/kick", + new UserIdAndReason() { UserId = userId, Reason = reason }); + + public async Task BanAsync(string userId, string? reason = null) => + await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/ban", + new UserIdAndReason() { UserId = userId, Reason = reason }); + + public async Task UnbanAsync(string userId) => + await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/unban", + new UserIdAndReason() { UserId = userId }); + + public async Task SendStateEventAsync(string eventType, object content) => + await (await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType}", content)) + .Content.ReadFromJsonAsync(); + + public async Task SendMessageEventAsync(string eventType, RoomMessageEventData content) { + var res = await _httpClient.PutAsJsonAsync( + $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(), content); + var resu = await res.Content.ReadFromJsonAsync(); + return resu; + } + + public async Task SendFileAsync(string eventType, string fileName, Stream fileStream) { + var content = new MultipartFormDataContent(); + content.Add(new StreamContent(fileStream), "file", fileName); + var res = await + ( + await _httpClient.PutAsync( + $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(), + content + ) + ) + .Content.ReadFromJsonAsync(); + return res; + } + + public readonly SpaceRoom AsSpace; +} diff --git a/LibMatrix/RoomTypes/SpaceRoom.cs b/LibMatrix/RoomTypes/SpaceRoom.cs new file mode 100644 index 0000000..ff2c228 --- /dev/null +++ b/LibMatrix/RoomTypes/SpaceRoom.cs @@ -0,0 +1,25 @@ +using LibMatrix.Extensions; + +namespace LibMatrix.RoomTypes; + +public class SpaceRoom : GenericRoom { + private readonly AuthenticatedHomeServer _homeServer; + private readonly GenericRoom _room; + + public SpaceRoom(AuthenticatedHomeServer homeServer, string roomId) : base(homeServer, roomId) { + _homeServer = homeServer; + } + + private static SemaphoreSlim _semaphore = new(1, 1); + public async IAsyncEnumerable GetRoomsAsync(bool includeRemoved = false) { + await _semaphore.WaitAsync(); + var rooms = new List(); + var state = GetFullStateAsync(); + await foreach (var stateEvent in state) { + if (stateEvent.Type != "m.space.child") continue; + if (stateEvent.RawContent.ToJson() != "{}" || includeRemoved) + yield return await _homeServer.GetRoom(stateEvent.StateKey); + } + _semaphore.Release(); + } +} -- cgit 1.4.1