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);
}
}