using System.Text.Json; using System.Threading.Tasks; using Uwaa.HTTP; using Uwaa.Pleroma.API; namespace Uwaa.Pleroma; /// /// A pleroma client. /// public class Pleroma { static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNameCaseInsensitive = true, NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString, }; static readonly MIMEType JsonMIMEType = new("application", "json"); /// /// The hostname of the pleroma instance. /// public string Host; /// /// The full token, including the "Bearer" string. /// public string Authorization; /// /// The user agent string. /// public string UserAgent = "Uwaa.Pleroma/0.0"; public Pleroma(string host, string authorization) { Host = host; Authorization = authorization; } async Task RequestJSON(HttpRequest req) where T : class { req.Fields.UserAgent = UserAgent; req.Fields.Authorization = Authorization; HttpResponse res = await HttpClient.Request(Host, true, req); if (res.StatusCode == 404) return null; if (!res.Fields.ContentType.HasValue || !res.Fields.ContentType.Value.Match(JsonMIMEType)) throw new HttpException("Server did not respond with JSON" + (res.Content.HasValue ? ", got: " + res.Content.Value.AsText : null)); if (!res.Content.HasValue) throw new HttpException("Server responded with no content"); string text = res.Content.Value.AsText; if (res.StatusCode is >= 400 and < 600) { try { PleromaException? err = JsonSerializer.Deserialize(text, SerializerOptions); if (err != null && err.Text != null) throw err; } catch (JsonException) { //Not an error } } if (res.StatusCode is >= 200 and < 300) return JsonSerializer.Deserialize(text, SerializerOptions) ?? throw new HttpException("Couldn't deserialize response"); else throw new HttpException("Unknown error occurred"); } /// /// Posts a status. /// /// The status data to send, including the content, visibility, etc. /// The status, if posting was successful. public Task PostStatus(PublishStatus status) { HttpRequest req = new HttpRequest(HttpMethod.POST, "/api/v1/statuses"); req.Content = new HttpContent(JsonMIMEType, JsonSerializer.SerializeToUtf8Bytes(status, SerializerOptions)); req.Fields.Accept = [JsonMIMEType]; return RequestJSON(req)!; } /// /// Fetches the latest statuses from the public timeline. /// public Task GetTimeline() { //TODO: Parameters and selecting different timelines (home, public, bubble) HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/timelines/public"); req.Fields.Accept = [ JsonMIMEType ]; return RequestJSON(req)!; } /// /// Fetches the latest statuses from a user's timeline. /// public Task GetTimeline(Account account) => GetTimeline(account.ID); /// /// Fetches the latest statuses from a user's timeline. /// public Task GetTimeline(string account_id) { HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{account_id}/statuses"); req.Fields.Accept = [JsonMIMEType]; return RequestJSON(req)!; } /// /// Fetches the account of the pleroma client. /// public Task GetAccount() { HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/accounts/verify_credentials"); req.Fields.Accept = [JsonMIMEType]; return RequestJSON(req)!; } /// /// Fetches an account. /// public Task GetAccount(string id) { HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{id}"); req.Fields.Accept = [JsonMIMEType]; return RequestJSON(req); } /// /// Fetches the context of a status. /// public Task GetContext(Status status) => GetContext(status.ID); /// /// Fetches the context of a status. /// public Task GetContext(string status_id) { HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/statuses/{status_id}/context"); req.Fields.Accept = [JsonMIMEType]; return RequestJSON(req); } }