pleroma: cleanups and stuff
This commit is contained in:
parent
f61957e19c
commit
39bf03ae95
10 changed files with 326 additions and 114 deletions
|
@ -12,7 +12,7 @@ static class Program
|
||||||
|
|
||||||
static async Task MainInline()
|
static async Task MainInline()
|
||||||
{
|
{
|
||||||
Pleroma client = new Pleroma("alpine1.local", "Bearer Y52OX25r7rp3Lyqa-oTibk5_4sLapEKBIsxa5vWMRtw");
|
Pleroma client = new Pleroma("localhost", "Bearer abcdefghijklmnopqrstuvwxyz");
|
||||||
Account account = await client.GetAccount();
|
Account account = await client.GetAccount();
|
||||||
Status[] statuses = await client.GetTimeline();
|
Status[] statuses = await client.GetTimeline();
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,39 @@ namespace Uwaa.Pleroma.API;
|
||||||
[JsonConverter(typeof(PublishStatusConverter))]
|
[JsonConverter(typeof(PublishStatusConverter))]
|
||||||
public class PublishStatus
|
public class PublishStatus
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Text content of the status.
|
||||||
|
/// </summary>
|
||||||
public string Content { get; set; }
|
public string Content { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark status and attached media as sensitive?
|
||||||
|
/// </summary>
|
||||||
public bool Sensitive { get; set; }
|
public bool Sensitive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour.
|
||||||
|
/// </summary>
|
||||||
public int? ExpiresIn { get; set; } = null!;
|
public int? ExpiresIn { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID of the status being replied to, if status is a reply
|
||||||
|
/// </summary>
|
||||||
public string? ReplyTo { get; set; }
|
public string? ReplyTo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID of the status being quoted.
|
||||||
|
/// </summary>
|
||||||
|
public string? Quoting { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ISO 639 language code for this status.
|
||||||
|
/// </summary>
|
||||||
|
public string? Language { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visibility of the posted status.
|
||||||
|
/// </summary>
|
||||||
public StatusVisibility Visibility { get; set; } = StatusVisibility.Public;
|
public StatusVisibility Visibility { get; set; } = StatusVisibility.Public;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -65,6 +90,18 @@ class PublishStatusConverter : JsonConverter<PublishStatus>
|
||||||
writer.WriteStringValue(status.ReplyTo);
|
writer.WriteStringValue(status.ReplyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status.Quoting != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("quote_id");
|
||||||
|
writer.WriteStringValue(status.Quoting);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.Language != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("language");
|
||||||
|
writer.WriteStringValue(status.Language);
|
||||||
|
}
|
||||||
|
|
||||||
if (status.Visibility != StatusVisibility.Public)
|
if (status.Visibility != StatusVisibility.Public)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("visibility");
|
writer.WritePropertyName("visibility");
|
||||||
|
|
22
Pleroma/EnumLowerCaseConverter.cs
Normal file
22
Pleroma/EnumLowerCaseConverter.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts to and from enum values in lowercase.
|
||||||
|
/// </summary>
|
||||||
|
class EnumLowerCaseConverter<T> : JsonConverter<T> where T : struct
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum;
|
||||||
|
|
||||||
|
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
return Enum.Parse<T>(reader.GetString() ?? throw new NullReferenceException("Expected a string, got null"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(value.ToString()?.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
public class Account
|
public class Account
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pleroma uses 128-bit ids as opposed to Mastodon's 64 bits. However just like Mastodon's ids they are lexically sortable strings
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("id")]
|
[JsonPropertyName("id")]
|
||||||
public string ID { get; set; } = null!;
|
public string ID { get; set; } = null!;
|
||||||
|
|
||||||
|
|
20
Pleroma/Models/Hashtag.cs
Normal file
20
Pleroma/Models/Hashtag.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
|
public class Hashtag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the hashtag after the # sign
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A link to the hashtag on the instance
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("url")]
|
||||||
|
public string URL { get; set; } = null!;
|
||||||
|
|
||||||
|
public override string ToString() => $"#{Name}";
|
||||||
|
}
|
24
Pleroma/Models/SearchResults.cs
Normal file
24
Pleroma/Models/SearchResults.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
|
public class SearchResults
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Accounts which match the search query.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("accounts")]
|
||||||
|
public Account[]? Accounts { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hashtags which match the search query.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("hashtags")]
|
||||||
|
public Hashtag[]? Hashtags { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Statuses which match the search query.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("statuses")]
|
||||||
|
public Status[]? Statuses { get; set; }
|
||||||
|
}
|
|
@ -4,36 +4,72 @@ namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
public class Status
|
public class Status
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pleroma uses 128-bit ids as opposed to Mastodon's 64 bits. However just like Mastodon's ids they are lexically sortable strings
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("id")]
|
[JsonPropertyName("id")]
|
||||||
public string ID { get; set; } = null!;
|
public string ID { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HTML-encoded status content
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("content")]
|
[JsonPropertyName("content")]
|
||||||
public string HtmlContent { get; set; } = null!;
|
public string HtmlContent { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The account that authored this status
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("account")]
|
[JsonPropertyName("account")]
|
||||||
public Account Account { get; set; } = null!;
|
public Account Account { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date when this status was created
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("created_at")]
|
[JsonPropertyName("created_at")]
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("pleroma")]
|
[JsonPropertyName("pleroma")]
|
||||||
public PleromaObject Pleroma { get; set; } = null!;
|
public PleromaObject Pleroma { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID of the account being replied to
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("in_reply_to_account_id")]
|
[JsonPropertyName("in_reply_to_account_id")]
|
||||||
public string? ReplyToAccount { get; set; } = null;
|
public string? ReplyToAccount { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID of the status being replied
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("in_reply_to_id")]
|
[JsonPropertyName("in_reply_to_id")]
|
||||||
public string? ReplyToStatus { get; set; } = null;
|
public string? ReplyToStatus { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mentions of users within the status content
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("mentions")]
|
[JsonPropertyName("mentions")]
|
||||||
public Mention[] Mentions { get; set; } = Array.Empty<Mention>();
|
public Mention[] Mentions { get; set; } = Array.Empty<Mention>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Primary language of this status
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("language")]
|
[JsonPropertyName("language")]
|
||||||
public string? Language { get; set; }
|
public string? Language { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Have you pinned this status? Only appears if the status is pinnable.
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("pinned")]
|
[JsonPropertyName("pinned")]
|
||||||
public bool Pinned { get; set; }
|
public bool Pinned { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visibility of this status
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("visibility")]
|
||||||
|
public StatusVisibility Visibility { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plain text content of that status.
|
||||||
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string Content => Pleroma?.Content?.Plain ?? HtmlContent;
|
public string Content => Pleroma?.Content?.Plain ?? HtmlContent;
|
||||||
|
|
||||||
|
@ -49,6 +85,29 @@ public class Mention
|
||||||
{
|
{
|
||||||
public static implicit operator string(Mention mention) => mention.ID;
|
public static implicit operator string(Mention mention) => mention.ID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The webfinger acct: URI of the mentioned user. Equivalent to <c>username</c> for local users, or <c>username@domain</c> for remote users.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("acct")]
|
||||||
|
public string Account { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The account id of the mentioned user
|
||||||
|
/// </summary>
|
||||||
[JsonPropertyName("id")]
|
[JsonPropertyName("id")]
|
||||||
public string ID { get; set; } = null!;
|
public string ID { get; set; } = null!;
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// The location of the mentioned user's profile
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("url")]
|
||||||
|
public string URL { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The username of the mentioned user
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("username")]
|
||||||
|
public string Username { get; set; } = null!;
|
||||||
|
|
||||||
|
public override string ToString() => $"@{Account}";
|
||||||
|
}
|
||||||
|
|
|
@ -40,134 +40,118 @@ public class Pleroma
|
||||||
Authorization = authorization;
|
Authorization = authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task RequestJSONRetry(HttpRequest req)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await RequestJSON(req);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (PleromaException e)
|
|
||||||
{
|
|
||||||
if (e.Text == "Throttled")
|
|
||||||
{
|
|
||||||
await Task.Delay(5000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task<T?> RequestJSONRetry<T>(HttpRequest req) where T : class
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await RequestJSON<T>(req);
|
|
||||||
}
|
|
||||||
catch (PleromaException e)
|
|
||||||
{
|
|
||||||
if (e.Text == "Throttled")
|
|
||||||
{
|
|
||||||
await Task.Delay(5000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task RequestJSON(HttpRequest req)
|
async Task RequestJSON(HttpRequest req)
|
||||||
{
|
{
|
||||||
req.Fields.UserAgent = UserAgent;
|
req.Fields.UserAgent = UserAgent;
|
||||||
req.Fields.Authorization = Authorization;
|
req.Fields.Authorization = Authorization;
|
||||||
|
while (true)
|
||||||
HttpResponse res = await HttpClient.Request(Host, true, req);
|
|
||||||
|
|
||||||
if (res.StatusCode == 404)
|
|
||||||
return;
|
|
||||||
|
|
||||||
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
|
HttpResponse res = await HttpClient.Request(Host, true, req);
|
||||||
{
|
|
||||||
PleromaException? err = JsonSerializer.Deserialize<PleromaException>(text, SerializerOptions);
|
|
||||||
if (err != null && err.Text != null)
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
catch (JsonException)
|
|
||||||
{
|
|
||||||
//Not an error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.StatusCode is not >= 200 or not < 300)
|
if (res.StatusCode == 404)
|
||||||
throw new HttpException("Unknown error occurred");
|
return;
|
||||||
|
|
||||||
|
if (res.Content.HasValue)
|
||||||
|
{
|
||||||
|
if (res.Fields.ContentType.HasValue && !res.Fields.ContentType.Value.Match(JsonMIMEType))
|
||||||
|
throw new HttpException(res.Content.Value.AsText);
|
||||||
|
|
||||||
|
if (res.StatusCode is >= 400 and < 600)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string text = res.Content.Value.AsText;
|
||||||
|
PleromaException? err = JsonSerializer.Deserialize<PleromaException>(text, SerializerOptions);
|
||||||
|
if (err != null && err.Text != null)
|
||||||
|
{
|
||||||
|
if (err.Text == "Throttled")
|
||||||
|
{
|
||||||
|
await Task.Delay(5000);
|
||||||
|
continue; //Retry
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
//Not an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.StatusCode is not >= 200 or not < 300)
|
||||||
|
throw new HttpException("Unknown error occurred");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<T?> RequestJSON<T>(HttpRequest req) where T : class
|
async Task<T?> RequestJSON<T>(HttpRequest req) where T : class
|
||||||
{
|
{
|
||||||
req.Fields.UserAgent = UserAgent;
|
req.Fields.UserAgent = UserAgent;
|
||||||
req.Fields.Authorization = Authorization;
|
req.Fields.Authorization = Authorization;
|
||||||
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
HttpResponse res = await HttpClient.Request(Host, true, req);
|
while (true)
|
||||||
|
|
||||||
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
|
HttpResponse res = await HttpClient.Request(Host, true, req);
|
||||||
{
|
|
||||||
PleromaException? err = JsonSerializer.Deserialize<PleromaException>(text, SerializerOptions);
|
|
||||||
if (err != null && err.Text != null)
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
catch (JsonException)
|
|
||||||
{
|
|
||||||
//Not an error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.StatusCode is >= 200 and < 300)
|
if (res.StatusCode == 404)
|
||||||
return JsonSerializer.Deserialize<T>(text, SerializerOptions) ?? throw new HttpException("Couldn't deserialize response");
|
return null;
|
||||||
else
|
|
||||||
throw new HttpException("Unknown error occurred");
|
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<PleromaException>(text, SerializerOptions);
|
||||||
|
if (err != null && err.Text != null)
|
||||||
|
{
|
||||||
|
if (err.Text == "Throttled")
|
||||||
|
{
|
||||||
|
await Task.Delay(5000);
|
||||||
|
continue; //Retry
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
//Not an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.StatusCode is >= 200 and < 300)
|
||||||
|
return JsonSerializer.Deserialize<T>(text, SerializerOptions) ?? throw new HttpException("Couldn't deserialize response");
|
||||||
|
else
|
||||||
|
throw new HttpException("Unknown error occurred");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Posts a status.
|
/// Posts a status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="status">The status data to send, including the content, visibility, etc.</param>
|
/// <param name="status">The status data to send, including the content, visibility, etc.</param>
|
||||||
/// <returns>The status, if posting was successful.</returns>
|
/// <exception cref="HttpException">Thrown if something goes wrong while uploading the status.</exception>
|
||||||
public Task<Status> PostStatus(PublishStatus status)
|
/// <returns>The status if posting was successful.</returns>
|
||||||
|
public async Task<Status> PostStatus(PublishStatus status)
|
||||||
{
|
{
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.POST, "/api/v1/statuses");
|
HttpRequest req = new HttpRequest(HttpMethod.POST, "/api/v1/statuses");
|
||||||
req.Content = new HttpContent(JsonMIMEType, JsonSerializer.SerializeToUtf8Bytes(status, SerializerOptions));
|
req.Content = new HttpContent(JsonMIMEType, JsonSerializer.SerializeToUtf8Bytes(status, SerializerOptions));
|
||||||
req.Fields.Accept = [JsonMIMEType];
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
return RequestJSONRetry<Status>(req)!;
|
Status result = (await RequestJSON<Status>(req))!;
|
||||||
|
status.OnPublish?.Invoke();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -178,7 +162,7 @@ public class Pleroma
|
||||||
//TODO: Parameters and selecting different timelines (home, public, bubble)
|
//TODO: Parameters and selecting different timelines (home, public, bubble)
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/timelines/public");
|
HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/timelines/public");
|
||||||
req.Fields.Accept = [ JsonMIMEType ];
|
req.Fields.Accept = [ JsonMIMEType ];
|
||||||
return RequestJSONRetry<Status[]>(req)!;
|
return RequestJSON<Status[]>(req)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -194,7 +178,7 @@ public class Pleroma
|
||||||
{
|
{
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{account_id}/statuses");
|
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{account_id}/statuses");
|
||||||
req.Fields.Accept = [JsonMIMEType];
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
return RequestJSONRetry<Status[]>(req)!;
|
return RequestJSON<Status[]>(req)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -204,7 +188,7 @@ public class Pleroma
|
||||||
{
|
{
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/accounts/verify_credentials");
|
HttpRequest req = new HttpRequest(HttpMethod.GET, "/api/v1/accounts/verify_credentials");
|
||||||
req.Fields.Accept = [JsonMIMEType];
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
return RequestJSONRetry<Account>(req)!;
|
return RequestJSON<Account>(req)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -214,7 +198,7 @@ public class Pleroma
|
||||||
{
|
{
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{id}");
|
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/accounts/{id}");
|
||||||
req.Fields.Accept = [JsonMIMEType];
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
return RequestJSONRetry<Account>(req);
|
return RequestJSON<Account>(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -230,7 +214,17 @@ public class Pleroma
|
||||||
{
|
{
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/statuses/{status_id}/context");
|
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/statuses/{status_id}/context");
|
||||||
req.Fields.Accept = [JsonMIMEType];
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
return RequestJSONRetry<Context>(req);
|
return RequestJSON<Context>(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches a status.
|
||||||
|
/// </summary>
|
||||||
|
public Task<Status?> GetStatus(string status_id)
|
||||||
|
{
|
||||||
|
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v1/statuses/{status_id}");
|
||||||
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
|
return RequestJSON<Status>(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -246,6 +240,46 @@ public class Pleroma
|
||||||
{
|
{
|
||||||
HttpRequest req = new HttpRequest(HttpMethod.DELETE, $"/api/v1/statuses/{status_id}");
|
HttpRequest req = new HttpRequest(HttpMethod.DELETE, $"/api/v1/statuses/{status_id}");
|
||||||
req.Fields.Accept = [JsonMIMEType];
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
return RequestJSONRetry(req);
|
return RequestJSON(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches for an accounts, hashtags, and/or statuses.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">What to search for</param>
|
||||||
|
/// <param name="account_id">If provided, statuses returned will be authored only by this account</param>
|
||||||
|
/// <param name="type">Search type</param>
|
||||||
|
/// <param name="resolve">Attempt WebFinger lookup</param>
|
||||||
|
/// <param name="following">Only include accounts that the user is following</param>
|
||||||
|
/// <param name="max_id">Return items older than this ID</param>
|
||||||
|
/// <param name="min_id">Return the oldest items newer than this ID</param>
|
||||||
|
/// <param name="since_id">Return the newest items newer than this ID</param>
|
||||||
|
/// <param name="offset">Return items past this number of items</param>
|
||||||
|
/// <param name="limit">Maximum number of items to return. Will be ignored if it's more than 40</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task<SearchResults> Search(string query,
|
||||||
|
string? account_id = null,
|
||||||
|
SearchType type = SearchType.All,
|
||||||
|
bool resolve = false,
|
||||||
|
bool following = false,
|
||||||
|
string? max_id = null,
|
||||||
|
string? min_id = null,
|
||||||
|
string? since_id = null,
|
||||||
|
int offset = 0,
|
||||||
|
int limit = 20)
|
||||||
|
{
|
||||||
|
HttpRequest req = new HttpRequest(HttpMethod.GET, $"/api/v2/search");
|
||||||
|
req.Fields.Accept = [JsonMIMEType];
|
||||||
|
req.Query["q"] = query;
|
||||||
|
if (account_id != null) req.Query["account_id"] = account_id;
|
||||||
|
if (type != SearchType.All) req.Query["type"] = type.ToString().ToLowerInvariant();
|
||||||
|
if (resolve) req.Query["resolve"] = "true";
|
||||||
|
if (following) req.Query["following"] = "true";
|
||||||
|
if (max_id != null) req.Query["max_id"] = max_id;
|
||||||
|
if (min_id != null) req.Query["min_id"] = min_id;
|
||||||
|
if (since_id != null) req.Query["since_id"] = since_id;
|
||||||
|
if (offset > 0) req.Query["offset"] = offset.ToString();
|
||||||
|
if (limit != 20) req.Query["limit"] = limit.ToString();
|
||||||
|
return RequestJSON<SearchResults>(req)!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
Pleroma/SearchType.cs
Normal file
9
Pleroma/SearchType.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
|
public enum SearchType
|
||||||
|
{
|
||||||
|
All,
|
||||||
|
Accounts,
|
||||||
|
Hashtags,
|
||||||
|
Statuses
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
namespace Uwaa.Pleroma;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Uwaa.Pleroma;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(EnumLowerCaseConverter<StatusVisibility>))]
|
||||||
public enum StatusVisibility
|
public enum StatusVisibility
|
||||||
{
|
{
|
||||||
Public,
|
Public,
|
||||||
Unlisted,
|
Unlisted,
|
||||||
Private,
|
|
||||||
Local,
|
Local,
|
||||||
|
Private,
|
||||||
Direct,
|
Direct,
|
||||||
|
List
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue