pleroma: cleanups and new stuff
This commit is contained in:
parent
c8f1924bd0
commit
460564b2f9
10 changed files with 576 additions and 86 deletions
|
@ -24,7 +24,7 @@ static class Program
|
|||
|
||||
Pleroma client = new Pleroma("localhost", "Bearer abcdefghijklmnopqrstuvwxyz");
|
||||
Account account = await client.GetAccount();
|
||||
Status[] statuses = await client.GetTimeline();
|
||||
Status[] statuses = await client.GetTimeline(Timeline.Bubble);
|
||||
|
||||
Console.WriteLine($"Account: {account} ({account.ID})");
|
||||
Console.WriteLine("Public statuses:");
|
||||
|
|
|
@ -14,14 +14,8 @@ public class Account
|
|||
[JsonPropertyName("display_name")]
|
||||
public string DisplayName { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("username")]
|
||||
public string Username { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("statuses_count")]
|
||||
public uint StatusesCount { get; set; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string URL { get; set; } = null!;
|
||||
[JsonPropertyName("fields")]
|
||||
public AccountField[] Fields { get; set; } = Array.Empty<AccountField>();
|
||||
|
||||
[JsonPropertyName("followers_count")]
|
||||
public uint Followers { get; set; }
|
||||
|
@ -29,5 +23,52 @@ public class Account
|
|||
[JsonPropertyName("following_count")]
|
||||
public uint Following { get; set; }
|
||||
|
||||
[JsonPropertyName("local")]
|
||||
public bool Local { get; set; }
|
||||
|
||||
[JsonPropertyName("locked")]
|
||||
public bool Locked { get; set; }
|
||||
|
||||
[JsonPropertyName("note")]
|
||||
public string Bio { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("statuses_count")]
|
||||
public uint StatusesCount { get; set; }
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string URL { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("username")]
|
||||
public string Username { get; set; } = null!;
|
||||
|
||||
public override string ToString() => $"@{Username}";
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(AccountIDConverter))]
|
||||
public readonly struct AccountID(string id)
|
||||
{
|
||||
public static implicit operator AccountID(string id) => new AccountID(id);
|
||||
|
||||
public static implicit operator AccountID(Account account) => new AccountID(account.ID);
|
||||
|
||||
public static implicit operator AccountID(Relationship relationship) => new AccountID(relationship.ID);
|
||||
|
||||
public readonly string ID = id;
|
||||
|
||||
public override string ToString() => ID;
|
||||
}
|
||||
|
||||
class AccountIDConverter : JsonConverter<AccountID>
|
||||
{
|
||||
public override bool CanConvert(Type type) => type.IsAssignableTo(typeof(AccountID));
|
||||
|
||||
public override AccountID Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return new AccountID(reader.GetString() ?? throw new NullReferenceException("Expected a string, got null"));
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, AccountID value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ID);
|
||||
}
|
||||
}
|
12
Pleroma/Models/AccountField.cs
Normal file
12
Pleroma/Models/AccountField.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
namespace Uwaa.Pleroma;
|
||||
|
||||
public class AccountField
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public string Value { get; set; } = null!;
|
||||
|
||||
public DateTime? VerifiedAt { get; set; }
|
||||
}
|
79
Pleroma/Models/Attachment.cs
Normal file
79
Pleroma/Models/Attachment.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
namespace Uwaa.Pleroma;
|
||||
|
||||
public class Attachment
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the attachment in the database.
|
||||
/// </summary>
|
||||
[JsonPropertyName("id")]
|
||||
public string ID { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Alternate text that describes what is in the media attachment, to be used for the visually impaired or when media attachments do not load
|
||||
/// </summary>
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional pleroma-specific data.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pleroma")]
|
||||
public PleromaAttachmentData Pleroma { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The location of a scaled-down preview of the attachment
|
||||
/// </summary>
|
||||
[JsonPropertyName("preview_url")]
|
||||
public string PreviewURL { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The location of the full-size original attachment on the remote website. String (URL), or null if the attachment is local
|
||||
/// </summary>
|
||||
[JsonPropertyName("remote_url")]
|
||||
public string? RemoteURL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A shorter URL for the attachment
|
||||
/// </summary>
|
||||
[JsonPropertyName("text_url")]
|
||||
public string? TextURL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of the attachment
|
||||
/// </summary>
|
||||
[JsonPropertyName("type")]
|
||||
public AttachmentType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The location of the original full-size attachment
|
||||
/// </summary>
|
||||
[JsonPropertyName("url")]
|
||||
public string URL { get; set; } = null!;
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(EnumLowerCaseConverter<AttachmentType>))]
|
||||
public enum AttachmentType
|
||||
{
|
||||
Unknown,
|
||||
Image,
|
||||
Video,
|
||||
Audio,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Additional pleroma-specific data for an <see cref="Attachment"/>.
|
||||
/// </summary>
|
||||
public class PleromaAttachmentData
|
||||
{
|
||||
/// <summary>
|
||||
/// MIME type of the attachment
|
||||
/// </summary>
|
||||
[JsonPropertyName("mime_type")]
|
||||
public string Content { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the attachment, typically the filename
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = null!;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
namespace Uwaa.Pleroma;
|
||||
|
||||
public class PleromaObject
|
||||
{
|
||||
[JsonPropertyName("content")]
|
||||
public Content Content { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("local")]
|
||||
public bool Local { get; set; }
|
||||
}
|
||||
|
||||
public class Content
|
||||
{
|
||||
[JsonPropertyName("text/plain")]
|
||||
public string Plain { get; set; } = null!;
|
||||
}
|
52
Pleroma/Models/Relationship.cs
Normal file
52
Pleroma/Models/Relationship.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
namespace Uwaa.Pleroma;
|
||||
|
||||
/// <summary>
|
||||
/// A relationship with another account.
|
||||
/// </summary>
|
||||
public class Relationship
|
||||
{
|
||||
/// <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")]
|
||||
public string ID { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("blocked_by")]
|
||||
public bool BlockedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("blocking")]
|
||||
public bool Blocking { get; set; }
|
||||
|
||||
[JsonPropertyName("domain_blocking")]
|
||||
public bool DomainBlocking { get; set; }
|
||||
|
||||
[JsonPropertyName("endorsed")]
|
||||
public bool Endorsed { get; set; }
|
||||
|
||||
[JsonPropertyName("followed_by")]
|
||||
public bool FollowedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("following")]
|
||||
public bool Following { get; set; }
|
||||
|
||||
[JsonPropertyName("muting")]
|
||||
public bool Muting { get; set; }
|
||||
|
||||
[JsonPropertyName("muting_notifications")]
|
||||
public bool MutingNotifications { get; set; }
|
||||
|
||||
[JsonPropertyName("note")]
|
||||
public string Note { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("notifying")]
|
||||
public bool Notifying { get; set; }
|
||||
|
||||
[JsonPropertyName("requested")]
|
||||
public bool Requested { get; set; }
|
||||
|
||||
[JsonPropertyName("showing_reblogs")]
|
||||
public bool ShowingReblogs { get; set; }
|
||||
|
||||
[JsonPropertyName("subscribing")]
|
||||
public bool Subscribing { get; set; }
|
||||
}
|
|
@ -26,8 +26,17 @@ public class Status
|
|||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("pleroma")]
|
||||
public PleromaObject Pleroma { get; set; } = null!;
|
||||
/// <summary>
|
||||
/// Have you favourited this status?
|
||||
/// </summary>
|
||||
[JsonPropertyName("favourited")]
|
||||
public bool Favourited { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many favourites this status has received
|
||||
/// </summary>
|
||||
[JsonPropertyName("favourites_count")]
|
||||
public int FavouriteCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID of the account being replied to
|
||||
|
@ -39,13 +48,7 @@ public class Status
|
|||
/// ID of the status being replied
|
||||
/// </summary>
|
||||
[JsonPropertyName("in_reply_to_id")]
|
||||
public string? ReplyToStatus { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Mentions of users within the status content
|
||||
/// </summary>
|
||||
[JsonPropertyName("mentions")]
|
||||
public Mention[] Mentions { get; set; } = Array.Empty<Mention>();
|
||||
public string? ReplyTo { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Primary language of this status
|
||||
|
@ -53,12 +56,84 @@ public class Status
|
|||
[JsonPropertyName("language")]
|
||||
public string? Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Media that is attached to this status
|
||||
/// </summary>
|
||||
[JsonPropertyName("media_attachments")]
|
||||
public Attachment[] Attachments { get; set; } = Array.Empty<Attachment>();
|
||||
|
||||
/// <summary>
|
||||
/// Mentions of users within the status content
|
||||
/// </summary>
|
||||
[JsonPropertyName("mentions")]
|
||||
public Mention[] Mentions { get; set; } = Array.Empty<Mention>();
|
||||
|
||||
/// <summary>
|
||||
/// Have you pinned this status? Only appears if the status is pinnable.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pinned")]
|
||||
public bool Pinned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional pleroma-specific data.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pleroma")]
|
||||
public PleromaStatusData Pleroma { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The status being reblogged
|
||||
/// </summary>
|
||||
[JsonPropertyName("reblog")]
|
||||
public Status? Reblog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Have you boosted this status?
|
||||
/// </summary>
|
||||
[JsonPropertyName("reblogged")]
|
||||
public bool Reblogged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many boosts this status has received
|
||||
/// </summary>
|
||||
[JsonPropertyName("reblogs_count")]
|
||||
public int ReblogCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many replies this status has received
|
||||
/// </summary>
|
||||
[JsonPropertyName("replies_count")]
|
||||
public int ReplyCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this status marked as sensitive content?
|
||||
/// </summary>
|
||||
[JsonPropertyName("sensitive")]
|
||||
public bool Sensitive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Subject or summary line, below which status content is collapsed until expanded
|
||||
/// </summary>
|
||||
[JsonPropertyName("spoiler_text")]
|
||||
public string SpoilerText { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Hashtags included in the status.
|
||||
/// </summary>
|
||||
[JsonPropertyName("tags")]
|
||||
public Hashtag[] Tags { get; set; } = Array.Empty<Hashtag>();
|
||||
|
||||
/// <summary>
|
||||
/// URI of the status used for federation
|
||||
/// </summary>
|
||||
[JsonPropertyName("uri")]
|
||||
public string URI { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// A link to the status's HTML representation
|
||||
/// </summary>
|
||||
[JsonPropertyName("url")]
|
||||
public string? URL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Visibility of this status
|
||||
/// </summary>
|
||||
|
@ -71,7 +146,11 @@ public class Status
|
|||
[JsonIgnore]
|
||||
public string Content => Pleroma?.Content?.Plain ?? HtmlContent;
|
||||
|
||||
public bool CheckMention(string id)
|
||||
/// <summary>
|
||||
/// Returns true if a status mentions or replies to a user.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the user.</param>
|
||||
public bool IsInteracting(string id)
|
||||
{
|
||||
return ReplyToAccount == id || Mentions.Any(m => m.ID == id);
|
||||
}
|
||||
|
@ -109,3 +188,48 @@ public class Mention
|
|||
|
||||
public override string ToString() => $"@{Account}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Additional pleroma-specific data for a <see cref="Status"/>.
|
||||
/// </summary>
|
||||
public class PleromaStatusData
|
||||
{
|
||||
[JsonPropertyName("content")]
|
||||
public Content Content { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("local")]
|
||||
public bool Local { get; set; }
|
||||
}
|
||||
|
||||
public class Content
|
||||
{
|
||||
[JsonPropertyName("text/plain")]
|
||||
public string Plain { get; set; } = null!;
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StatusIDConverter))]
|
||||
public readonly struct StatusID(string id)
|
||||
{
|
||||
public static implicit operator StatusID(string id) => new StatusID(id);
|
||||
|
||||
public static implicit operator StatusID(Status status) => new StatusID(status.ID);
|
||||
|
||||
public readonly string ID = id;
|
||||
|
||||
public override string ToString() => ID;
|
||||
}
|
||||
|
||||
class StatusIDConverter : JsonConverter<StatusID>
|
||||
{
|
||||
public override bool CanConvert(Type type) => type.IsAssignableTo(typeof(StatusID));
|
||||
|
||||
public override StatusID Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return new StatusID(reader.GetString() ?? throw new NullReferenceException("Expected a string, got null"));
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, StatusID value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ID);
|
||||
}
|
||||
}
|
|
@ -96,6 +96,80 @@ public class Pleroma
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the account of the pleroma client.
|
||||
/// </summary>
|
||||
public Task<Account> GetAccount() => Retry<Account>(new HttpRequestMessage(HttpMethod.Get, "/api/v1/accounts/verify_credentials"))!;
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an account by ID.
|
||||
/// </summary>
|
||||
/// <param name="id">Account ID to fetch</param>
|
||||
public Task<Account?> GetAccountByID(string id) => Retry<Account>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/accounts/{WebUtility.UrlEncode(id)}"));
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an account by nickname.
|
||||
/// </summary>
|
||||
/// <param name="acct">User nickname</param>
|
||||
public Task<Account?> GetAccountByName(string acct) => Retry<Account>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/accounts/lookup?acct={WebUtility.UrlEncode(acct)}"));
|
||||
|
||||
/// <summary>
|
||||
/// Follows the given account.
|
||||
/// </summary>
|
||||
/// <param name="id">Account to follow</param>
|
||||
/// <returns>The new relationship, if the provided account exists.</returns>
|
||||
public Task<Relationship?> Follow(AccountID account) => Retry<Relationship>(new HttpRequestMessage(HttpMethod.Post, $"/api/v1/accounts/{WebUtility.UrlEncode(account.ID)}/follow"));
|
||||
|
||||
/// <summary>
|
||||
/// Unfollows the given account.
|
||||
/// </summary>
|
||||
/// <param name="id">Account to unfollow</param>
|
||||
/// <returns>The new state of the relationship, if the provided account exists.</returns>
|
||||
public Task<Relationship?> Unfollow(AccountID account) => Retry<Relationship>(new HttpRequestMessage(HttpMethod.Post, $"/api/v1/accounts/{WebUtility.UrlEncode(account.ID)}/unfollow"));
|
||||
|
||||
/// <summary>
|
||||
/// Sets a private note for the given account.
|
||||
/// </summary>
|
||||
/// <param name="id">Account ID</param>
|
||||
/// <param name="comment">Account note body</param>
|
||||
/// <returns></returns>
|
||||
public Task<Relationship?> SetUserNote(AccountID account, string comment)
|
||||
{
|
||||
MemoryStream mem = new MemoryStream();
|
||||
|
||||
{
|
||||
Utf8JsonWriter writer = new Utf8JsonWriter(mem, new JsonWriterOptions() { SkipValidation = true });
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WritePropertyName("comment");
|
||||
writer.WriteStringValue(comment);
|
||||
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
mem.Position = 0;
|
||||
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, $"/api/v1/accounts/{WebUtility.UrlEncode(account.ID)}/note");
|
||||
req.Content = new StreamContent(mem);
|
||||
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
|
||||
return Retry<Relationship>(req)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the account's relationship with the given account.
|
||||
/// </summary>
|
||||
/// <param name="id">Account ID</param>
|
||||
/// <returns>A relationship object for the requested account, if the account exists.</returns>
|
||||
public async Task<Relationship?> GetRelationship(AccountID account)
|
||||
{
|
||||
Relationship[]? rels = await Retry<Relationship[]>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/accounts/relationships?id={WebUtility.UrlEncode(account.ID)}"));
|
||||
if (rels == null || rels.Length == 0)
|
||||
return null;
|
||||
else
|
||||
return rels[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts a status.
|
||||
/// </summary>
|
||||
|
@ -177,82 +251,166 @@ public class Pleroma
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the latest statuses from the public timeline.
|
||||
/// Reposts/boosts/shares a status.
|
||||
/// </summary>
|
||||
public Task<Status[]> GetTimeline()
|
||||
/// <param name="status">The status to reblog.</param>
|
||||
/// <returns>The reblogged status, if it exists.</returns>
|
||||
public Task<Status?> Reblog(StatusID status, StatusVisibility? visibility = null)
|
||||
{
|
||||
//TODO: Parameters and selecting different timelines (home, public, bubble)
|
||||
MemoryStream mem = new MemoryStream();
|
||||
|
||||
return Retry<Status[]>(new HttpRequestMessage(HttpMethod.Get, "/api/v1/timelines/public"))!;
|
||||
{
|
||||
Utf8JsonWriter writer = new Utf8JsonWriter(mem, new JsonWriterOptions() { SkipValidation = true });
|
||||
writer.WriteStartObject();
|
||||
|
||||
if (visibility.HasValue)
|
||||
{
|
||||
writer.WritePropertyName("visibility");
|
||||
writer.WriteStringValue(visibility.Value.ToString().ToLowerInvariant());
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
mem.Position = 0;
|
||||
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, $"/api/v1/statuses/{WebUtility.UrlEncode(status.ID)}/reblog");
|
||||
req.Content = new StreamContent(mem);
|
||||
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
|
||||
return Retry<Status>(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a reblog.
|
||||
/// </summary>
|
||||
/// <param name="status">The reblogged status to undo.</param>
|
||||
/// <returns>The status, if it exists.</returns>
|
||||
public Task<Status?> Unreblog(StatusID status) => Retry<Status>(new HttpRequestMessage(HttpMethod.Post, $"/api/v1/statuses/{WebUtility.UrlEncode(status.ID)}/unreblog"))!;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Likes/favourites a status, adding it to the account's favourite list.
|
||||
/// </summary>
|
||||
/// <param name="status">The status to favourite.</param>
|
||||
/// <returns>The favourited status, if it exists.</returns>
|
||||
public Task<Status?> Favourite(StatusID status) => Retry<Status>(new HttpRequestMessage(HttpMethod.Post, $"/api/v1/statuses/{WebUtility.UrlEncode(status.ID)}/favourite"))!;
|
||||
|
||||
/// <summary>
|
||||
/// Unfavourites a favorited status, removing it from the account's favourite list.
|
||||
/// </summary>
|
||||
/// <param name="status">The status to unfavourite.</param>
|
||||
/// <returns>The status, if it exists.</returns>
|
||||
public Task<Status?> Unfavourite(StatusID status) => Retry<Status>(new HttpRequestMessage(HttpMethod.Post, $"/api/v1/statuses/{WebUtility.UrlEncode(status.ID)}/unfavourite"))!;
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the latest statuses from a standard timeline.
|
||||
/// </summary>
|
||||
public Task<Status[]> GetTimeline(Timeline timeline,
|
||||
bool local = false,
|
||||
string? instance = null,
|
||||
bool only_media = false,
|
||||
bool remote = false,
|
||||
bool with_muted = false,
|
||||
StatusVisibility[]? exclude_visibilities = null,
|
||||
ReplyVisibility? reply_visibility = null,
|
||||
string? max_id = null,
|
||||
string? min_id = null,
|
||||
string? since_id = null,
|
||||
int offset = 0,
|
||||
int limit = 20)
|
||||
{
|
||||
string timelineName;
|
||||
switch (timeline)
|
||||
{
|
||||
case Timeline.Direct:
|
||||
timelineName = "direct";
|
||||
break;
|
||||
case Timeline.Home:
|
||||
timelineName = "home";
|
||||
break;
|
||||
case Timeline.Local:
|
||||
timelineName = "public";
|
||||
local = true;
|
||||
break;
|
||||
case Timeline.Bubble:
|
||||
timelineName = "bubble";
|
||||
break;
|
||||
case Timeline.Public:
|
||||
timelineName = "public";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException("Invalid timeline", nameof(timeline));
|
||||
}
|
||||
|
||||
return Retry<Status[]>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/timelines/{timelineName}" + CreateQuery(addPair =>
|
||||
{
|
||||
if (local) addPair("local", "true");
|
||||
if (instance != null) addPair("instance", instance);
|
||||
if (only_media) addPair("only_media", "true");
|
||||
if (remote) addPair("remote", "true");
|
||||
if (with_muted) addPair("with_muted", "true");
|
||||
if (exclude_visibilities != null) addPair("exclude_visibilities", JsonSerializer.Serialize(exclude_visibilities));
|
||||
if (reply_visibility.HasValue) addPair("reply_visibility", reply_visibility.Value.ToString().ToLowerInvariant());
|
||||
if (max_id != null) addPair("max_id", max_id);
|
||||
if (min_id != null) addPair("min_id", min_id);
|
||||
if (since_id != null) addPair("since_id", since_id);
|
||||
if (offset > 0) addPair("offset", offset.ToString());
|
||||
if (limit != 20) addPair("limit", limit.ToString());
|
||||
})))!;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the latest statuses from a user's timeline.
|
||||
/// </summary>
|
||||
public Task<Status[]> GetTimeline(Account account)
|
||||
=> GetTimeline(account.ID);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the latest statuses from a user's timeline.
|
||||
/// </summary>
|
||||
public Task<Status[]> GetTimeline(string account_id)
|
||||
public Task<Status[]?> GetTimeline(AccountID account,
|
||||
bool pinned = false,
|
||||
string? tagged = null,
|
||||
bool only_media = false,
|
||||
bool with_muted = false,
|
||||
bool exclude_reblogs = false,
|
||||
bool exclude_replies = false,
|
||||
StatusVisibility[]? exclude_visibilities = null,
|
||||
string? max_id = null,
|
||||
string? min_id = null,
|
||||
string? since_id = null,
|
||||
int offset = 0,
|
||||
int limit = 20)
|
||||
{
|
||||
return Retry<Status[]>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/accounts/{account_id}/statuses"))!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the account of the pleroma client.
|
||||
/// </summary>
|
||||
public Task<Account> GetAccount()
|
||||
return Retry<Status[]>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/accounts/{WebUtility.UrlEncode(account.ID)}/statuses" + CreateQuery(addPair =>
|
||||
{
|
||||
return Retry<Account>(new HttpRequestMessage(HttpMethod.Get, "/api/v1/accounts/verify_credentials"))!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an account.
|
||||
/// </summary>
|
||||
public Task<Account?> GetAccount(string id)
|
||||
{
|
||||
return Retry<Account?>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/accounts/{id}"));
|
||||
if (pinned) addPair("pinned", "true");
|
||||
if (tagged != null) addPair("tagged", tagged);
|
||||
if (only_media) addPair("only_media", "true");
|
||||
if (with_muted) addPair("with_muted", "true");
|
||||
if (exclude_reblogs) addPair("exclude_reblogs", "true");
|
||||
if (exclude_replies) addPair("exclude_replies", "true");
|
||||
if (exclude_visibilities != null) addPair("exclude_visibilities", JsonSerializer.Serialize(exclude_visibilities));
|
||||
if (max_id != null) addPair("max_id", max_id);
|
||||
if (min_id != null) addPair("min_id", min_id);
|
||||
if (since_id != null) addPair("since_id", since_id);
|
||||
if (offset > 0) addPair("offset", offset.ToString());
|
||||
if (limit != 20) addPair("limit", limit.ToString());
|
||||
})));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the context of a status.
|
||||
/// </summary>
|
||||
public Task<Context?> GetContext(Status status)
|
||||
=> GetContext(status.ID);
|
||||
public Task<Context?> GetContext(StatusID status) => Retry<Context>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/statuses/{WebUtility.UrlEncode(status.ID)}/context"));
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the context of a status.
|
||||
/// Fetches a status by ID.
|
||||
/// </summary>
|
||||
public Task<Context?> GetContext(string status_id)
|
||||
{
|
||||
return Retry<Context?>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/statuses/{status_id}/context"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches a status.
|
||||
/// </summary>
|
||||
public Task<Status?> GetStatus(string status_id)
|
||||
{
|
||||
return Retry<Status?>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/statuses/{status_id}"));
|
||||
}
|
||||
public Task<Status?> GetStatus(string id) => Retry<Status>(new HttpRequestMessage(HttpMethod.Get, $"/api/v1/statuses/{WebUtility.UrlEncode(id)}"));
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a status.
|
||||
/// </summary>
|
||||
public Task Delete(Status status)
|
||||
=> Delete(status.ID);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a status by ID.
|
||||
/// </summary>
|
||||
public Task Delete(string status_id)
|
||||
{
|
||||
//TODO: Test
|
||||
return Retry<object?>(new HttpRequestMessage(HttpMethod.Delete, $"/api/v1/statuses/{status_id}"));
|
||||
}
|
||||
public Task<Status?> Delete(StatusID status) => Retry<Status>(new HttpRequestMessage(HttpMethod.Delete, $"/api/v1/statuses/{WebUtility.UrlEncode(status.ID)}"));
|
||||
|
||||
/// <summary>
|
||||
/// Searches for an accounts, hashtags, and/or statuses.
|
||||
|
|
8
Pleroma/ReplyVisibility.cs
Normal file
8
Pleroma/ReplyVisibility.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Uwaa.Pleroma;
|
||||
|
||||
[JsonConverter(typeof(EnumLowerCaseConverter<ReplyVisibility>))]
|
||||
public enum ReplyVisibility
|
||||
{
|
||||
Following,
|
||||
Self,
|
||||
}
|
32
Pleroma/Timeline.cs
Normal file
32
Pleroma/Timeline.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
namespace Uwaa.Pleroma;
|
||||
|
||||
/// <summary>
|
||||
/// Special timelines.
|
||||
/// </summary>
|
||||
public enum Timeline
|
||||
{
|
||||
/// <summary>
|
||||
/// Statuses with a "direct" scope addressed to the account.
|
||||
/// </summary>
|
||||
Direct,
|
||||
|
||||
/// <summary>
|
||||
/// Statuses from followed users.
|
||||
/// </summary>
|
||||
Home,
|
||||
|
||||
/// <summary>
|
||||
/// Statuses from the local instance.
|
||||
/// </summary>
|
||||
Local,
|
||||
|
||||
/// <summary>
|
||||
/// Statuses from instances in the instance's bubble.
|
||||
/// </summary>
|
||||
Bubble,
|
||||
|
||||
/// <summary>
|
||||
/// All statuses visible to the instance.
|
||||
/// </summary>
|
||||
Public,
|
||||
}
|
Loading…
Reference in a new issue