103 lines
4.0 KiB
C#
103 lines
4.0 KiB
C#
using decePubClient.Models.Mastodon;
|
|||
|
|
|
||
|
|
namespace decePubClient.Models;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// One item of a feed, whatever its source: a status (a boost shows its original, BoostedBy names the booster), a
|
||
|
|
/// notification, a direct conversation, or a located post from /clientapi/post/nearby (Located, with no Mastodon
|
||
|
|
/// actions: PrivaPub keeps those posts off the Mastodon API). Location is filled by InstanceService once the author's
|
||
|
|
/// server is known.
|
||
|
|
/// </summary>
|
||
|
|
public class FeedPost
|
||
|
|
{
|
||
|
|
/// <summary>Unique within a feed: the status, notification or conversation id.</summary>
|
||
|
|
public string Key { get; init; }
|
||
|
|
/// <summary>The id the feed pages by (max_id/min_id).</summary>
|
||
|
|
public string CursorId { get; init; }
|
||
|
|
/// <summary>The post shown; null for a notification without one (a follow).</summary>
|
||
|
|
public Status Status { get; set; }
|
||
|
|
public Account BoostedBy { get; init; }
|
||
|
|
public Notification Notification { get; init; }
|
||
|
|
public Conversation Conversation { get; init; }
|
||
|
|
/// <summary>A located post: within its range of the reader, never on the Mastodon API.</summary>
|
||
|
|
public bool Located { get; init; }
|
||
|
|
public double? DistanceKm { get; init; }
|
||
|
|
public double? RangeKm { get; init; }
|
||
|
|
public FeedLocation Location { get; set; }
|
||
|
|
|
||
|
|
/// <summary>The account the item is about: the post's author, or whoever caused the notification.</summary>
|
||
|
|
public Account Author => Status?.Account ?? Notification?.Account;
|
||
|
|
|
||
|
|
public string Host => Author?.Host;
|
||
|
|
|
||
|
|
public bool IsOwnedBy(string personaId) => personaId is not null && Status?.Account?.Id == personaId;
|
||
|
|
|
||
|
|
public static FeedPost Of(Status status) => status.Reblog is { } original
|
||
|
|
? new() { Key = status.Id, CursorId = status.Id, Status = original, BoostedBy = status.Account }
|
||
|
|
: new() { Key = status.Id, CursorId = status.Id, Status = status };
|
||
|
|
|
||
|
|
public static FeedPost Of(Notification notification) => new()
|
||
|
|
{
|
||
|
|
Key = notification.Id,
|
||
|
|
CursorId = notification.Id,
|
||
|
|
Status = notification.Status?.Reblog ?? notification.Status,
|
||
|
|
Notification = notification
|
||
|
|
};
|
||
|
|
|
||
|
|
public static FeedPost Of(Conversation conversation) => new()
|
||
|
|
{
|
||
|
|
Key = conversation.Id,
|
||
|
|
CursorId = conversation.LastStatus?.Id,
|
||
|
|
Status = conversation.LastStatus,
|
||
|
|
Conversation = conversation
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>Where a feed item is drawn on the globe, and how sure that is.</summary>
|
||
|
|
public enum LocationSource
|
||
|
|
{
|
||
|
|
/// <summary>The post's own place (Pixelfed): exact.</summary>
|
||
|
|
Place,
|
||
|
|
/// <summary>An event's venue: exact.</summary>
|
||
|
|
Event,
|
||
|
|
/// <summary>The author's server, to 0.1°.</summary>
|
||
|
|
Server,
|
||
|
|
/// <summary>The author's server, known only by country: a point in that country.</summary>
|
||
|
|
Country,
|
||
|
|
/// <summary>A located post, within its range of the reader: drawn at the reader.</summary>
|
||
|
|
NearYou
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed record FeedLocation(double Latitude, double Longitude, LocationSource Source, string Label, double PrecisionKm);
|
||
|
|
|
||
|
|
/// <summary>What the client keeps about a server (from /api/privapub/v1/instances), cached for a day.</summary>
|
||
|
|
public class ServerInfo
|
||
|
|
{
|
||
|
|
public string Host { get; set; }
|
||
|
|
public string Software { get; set; }
|
||
|
|
public string Version { get; set; }
|
||
|
|
public string NodeName { get; set; }
|
||
|
|
public bool? OpenRegistrations { get; set; }
|
||
|
|
public long? Users { get; set; }
|
||
|
|
public long? ActiveMonth { get; set; }
|
||
|
|
public long? LocalPosts { get; set; }
|
||
|
|
public InstanceLocation Geo { get; set; }
|
||
|
|
public int ConsecutiveFailures { get; set; }
|
||
|
|
public DateTime? LastSuccessAt { get; set; }
|
||
|
|
public DateTime? LastFailureAt { get; set; }
|
||
|
|
public DateTime? DescribedAt { get; set; }
|
||
|
|
public string DescriptionError { get; set; }
|
||
|
|
public DateTime FetchedAt { get; set; }
|
||
|
|
/// <summary>True when PrivaPub did not know the server: nothing to show, asked again later.</summary>
|
||
|
|
public bool Unknown { get; set; }
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>A page of a feed and the cursors around it.</summary>
|
||
|
|
public class FeedPage
|
||
|
|
{
|
||
|
|
public List<FeedPost> Posts { get; set; } = [];
|
||
|
|
/// <summary>Older items start below this id; null at the end of the feed.</summary>
|
||
|
|
public string MaxId { get; set; }
|
||
|
|
/// <summary>Newer items start above this id.</summary>
|
||
|
|
public string MinId { get; set; }
|
||
|
|
}
|