A post whose server is behind a CDN has no place of its own: the globe groups such posts per CDN in labels on a ring above the Arctic, and hovering one draws its arc to the CDN's group and a ring where the server was before the CDN. The card's CDN chip names the CDN, its domain, how PrivaPub found it (published ranges, response headers or network), the place before the CDN and the CDN's servers week by week (/api/privapub/v1/cdns/:domain); the author's tooltip lists the server's changes of place and CDN week by week (/instances/:host/history). Both are read on the first hover and kept for the session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
180 lines
5.9 KiB
C#
180 lines
5.9 KiB
C#
using System.Text.Json.Nodes;
|
|
|
|
namespace decePubClient.Models.Mastodon;
|
|
|
|
/// <summary>/api/privapub/v1/instances: what PrivaPub stored about a server, and where it is.</summary>
|
|
public class InstanceDescription
|
|
{
|
|
public string Host { get; set; }
|
|
public string Software { get; set; }
|
|
public string Version { get; set; }
|
|
public string NodeName { get; set; }
|
|
public List<string> Protocols { get; set; } = [];
|
|
public bool? OpenRegistrations { get; set; }
|
|
public DateTime? DescribedAt { get; set; }
|
|
public string DescriptionError { get; set; }
|
|
public JsonNode NodeInfo { get; set; }
|
|
public InstanceDelivery Delivery { get; set; }
|
|
public InstanceLocation Geo { get; set; }
|
|
}
|
|
|
|
public class InstanceDelivery
|
|
{
|
|
public int ConsecutiveFailures { get; set; }
|
|
public DateTime? UnavailableUntil { get; set; }
|
|
public DateTime? LastSuccessAt { get; set; }
|
|
public DateTime? LastFailureAt { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The public projection of a server's place. Precision: city (coordinates to 0.1°, city and network), country (located
|
|
/// only to a country) or cdn (the CDN's name, its domain, how PrivaPub found it, and where the server was before it).
|
|
/// </summary>
|
|
public class InstanceLocation
|
|
{
|
|
public string Precision { get; set; }
|
|
public string Country { get; set; }
|
|
public string City { get; set; }
|
|
public double? Latitude { get; set; }
|
|
public double? Longitude { get; set; }
|
|
public string Network { get; set; }
|
|
public string Cdn { get; set; }
|
|
public string CdnDomain { get; set; }
|
|
/// <summary>ranges (the CDN's published addresses), headers (its fingerprint in the server's answers) or asn.</summary>
|
|
public string CdnSource { get; set; }
|
|
public InstancePlace BeforeCdn { get; set; }
|
|
public string Source { get; set; }
|
|
public DateTime? LocatedAt { get; set; }
|
|
}
|
|
|
|
/// <summary>Where a server was in a week (an ISO week, "2026-W40").</summary>
|
|
public class InstancePlace
|
|
{
|
|
public string Week { get; set; }
|
|
public string Country { get; set; }
|
|
public string City { get; set; }
|
|
public double? Latitude { get; set; }
|
|
public double? Longitude { get; set; }
|
|
}
|
|
|
|
/// <summary>/api/privapub/v1/instances/{host}/history: one weekly snapshot of a server.</summary>
|
|
public class InstanceWeek
|
|
{
|
|
public string Week { get; set; }
|
|
public DateTime? TakenAt { get; set; }
|
|
public bool Reachable { get; set; }
|
|
public string Software { get; set; }
|
|
public string Version { get; set; }
|
|
public long? UsersTotal { get; set; }
|
|
public long? UsersActiveMonth { get; set; }
|
|
public long? LocalPosts { get; set; }
|
|
public bool? OpenRegistrations { get; set; }
|
|
public InstanceLocation Geo { get; set; }
|
|
}
|
|
|
|
/// <summary>/api/privapub/v1/cdns: a CDN as a group of servers, named by its own domain (Key).</summary>
|
|
public class CdnSummary
|
|
{
|
|
public string Key { get; set; }
|
|
public string Name { get; set; }
|
|
public string Domain { get; set; }
|
|
public int Servers { get; set; }
|
|
public int Ranges { get; set; }
|
|
public DateTime? RangesUpdatedAt { get; set; }
|
|
public List<string> DetectedBy { get; set; } = [];
|
|
}
|
|
|
|
/// <summary>/api/privapub/v1/cdns/{key}: the servers behind a CDN and, newest first, week by week who joined and left.</summary>
|
|
public class CdnDetail : CdnSummary
|
|
{
|
|
public List<string> Hosts { get; set; } = [];
|
|
public bool HostsTruncated { get; set; }
|
|
public List<CdnWeek> Weeks { get; set; } = [];
|
|
}
|
|
|
|
public class CdnWeek
|
|
{
|
|
public string Week { get; set; }
|
|
public int Servers { get; set; }
|
|
public List<string> Joined { get; set; } = [];
|
|
public List<string> Left { get; set; } = [];
|
|
}
|
|
|
|
/// <summary>/api/privapub/v1/statuses/{id}/provenance: how a remote post reached PrivaPub. Path is local for a local post.</summary>
|
|
public class Provenance
|
|
{
|
|
public string ObjectUri { get; set; }
|
|
public string ObjectType { get; set; }
|
|
public string Url { get; set; }
|
|
/// <summary>delivered, fetched, unrecorded or local.</summary>
|
|
public string Path { get; set; }
|
|
public bool Refetched { get; set; }
|
|
public ProvenanceActivity Activity { get; set; }
|
|
public string Inbox { get; set; }
|
|
public string FetchedBy { get; set; }
|
|
public ProvenanceSignature Signature { get; set; }
|
|
public DateTime? ReceivedAt { get; set; }
|
|
public DateTime? Published { get; set; }
|
|
public DateTime? Updated { get; set; }
|
|
public List<string> Extensions { get; set; } = [];
|
|
public List<string> ContextNamespaces { get; set; } = [];
|
|
public JsonNode Raw { get; set; }
|
|
public int RawBytes { get; set; }
|
|
public string RawHash { get; set; }
|
|
public bool RawTruncated { get; set; }
|
|
public List<ProvenanceRevision> Revisions { get; set; } = [];
|
|
public InstanceDescription Instance { get; set; }
|
|
}
|
|
|
|
public class ProvenanceActivity
|
|
{
|
|
public string Id { get; set; }
|
|
public string Type { get; set; }
|
|
public string Actor { get; set; }
|
|
}
|
|
|
|
public class ProvenanceSignature
|
|
{
|
|
public string Scheme { get; set; }
|
|
public string KeyId { get; set; }
|
|
public string Algorithm { get; set; }
|
|
public List<string> Headers { get; set; } = [];
|
|
}
|
|
|
|
public class ProvenanceRevision
|
|
{
|
|
public string ActivityId { get; set; }
|
|
public DateTime? Updated { get; set; }
|
|
public DateTime? ReceivedAt { get; set; }
|
|
public string RawHash { get; set; }
|
|
}
|
|
|
|
/// <summary>The answer of /oauth/token.</summary>
|
|
public class TokenResponse
|
|
{
|
|
public string AccessToken { get; set; }
|
|
public string TokenType { get; set; }
|
|
public string IssuedTokenType { get; set; }
|
|
public string Scope { get; set; }
|
|
public long CreatedAt { get; set; }
|
|
}
|
|
|
|
/// <summary>An error of the Mastodon API or of /oauth: {"error": ..., "error_description": ...}.</summary>
|
|
public class MastodonError
|
|
{
|
|
public string Error { get; set; }
|
|
public string ErrorDescription { get; set; }
|
|
}
|
|
|
|
/// <summary>POST /api/v1/statuses. The text is plain: the Mastodon API does not take Markdown.</summary>
|
|
public class PostStatusForm
|
|
{
|
|
public string Status { get; set; }
|
|
public List<string> MediaIds { get; set; } = [];
|
|
public string InReplyToId { get; set; }
|
|
public bool Sensitive { get; set; }
|
|
public string SpoilerText { get; set; }
|
|
public string Visibility { get; set; }
|
|
public string Language { get; set; }
|
|
}
|