Replies a post's author approves (FEP-5624), checked live with PeerTube
PeerTube puts canReply on a video whose comments wait for approval, and answers each comment with ApproveReply. A persona's reply to such a post now waits (privapub.approval: pending), its Create going to the author alone; the author's ApproveReply, signed by the author and naming the post answered, lets it out to its audience with replyApproval, and RejectReply leaves it ours. A null canReply (PeerTube's open comments) says nothing; an empty one refuses. The PeerTube scenario holds a comment for review and approves it through PeerTube's API (28 checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
5d5f1d6909
commit
a3a66b6db2
17 files changed
+256
-25
No files matched your search
@@ -44,6 +44,7 @@ namespace PrivaPub.Federation.Objects
|
||||
public InteractionRule ReplyPolicy { get; init; }
|
||||
public InteractionRule LikePolicy { get; init; }
|
||||
public InteractionRule AnnouncePolicy { get; init; }
|
||||
public InteractionRule ReplyApprovals { get; init; }//FEP-5624's canReply: who may reply, each reply then approved or refused
|
||||
public IReadOnlyList<CustomEmoji> Emojis { get; init; } = Array.Empty<CustomEmoji>();
|
||||
public string CoverURL { get; init; }
|
||||
public PostLink Link { get; init; }
|
||||
@@ -122,6 +123,7 @@ namespace PrivaPub.Federation.Objects
|
||||
ReplyPolicy = ObjectShapes.Policy(note, "canReply"),
|
||||
LikePolicy = ObjectShapes.Policy(note, "canLike"),
|
||||
AnnouncePolicy = ObjectShapes.Policy(note, "canAnnounce"),
|
||||
ReplyApprovals = ObjectShapes.ReplyApprovals(note),
|
||||
Emojis = ObjectShapes.Emojis(note["tag"]),
|
||||
CoverURL = ObjectShapes.Cover(note),
|
||||
Link = ObjectShapes.Link(note),
|
||||
|
||||
@@ -102,16 +102,23 @@ namespace PrivaPub.Federation.Objects
|
||||
|
||||
// one rule of a post's interactionPolicy (GoToSocial, FEP-044f): who may, automatically or once asked; the old names
|
||||
// (always, approvalRequired) too. A rule left out means anyone, automatically
|
||||
static List<string> Who(JsonNode node) => node switch
|
||||
{
|
||||
JsonArray array => array.Select(Id).Where(id => id != default).Take(MaxAudience).ToList(),
|
||||
JsonNode single when Id(single) is { } id => new List<string> { id },
|
||||
_ => new List<string>()
|
||||
};
|
||||
|
||||
// FEP-5624's canReply (PeerTube's, on a video whose comments wait for approval): who may reply, each reply then
|
||||
// approved by the author with an ApproveReply, or refused with a RejectReply; null when the post states none (PeerTube
|
||||
// sends null for a video whose comments are open, and an empty list where they are closed)
|
||||
public static InteractionRule ReplyApprovals(JsonObject note) =>
|
||||
note["canReply"] is { } canReply ? new InteractionRule { Manual = Who(canReply) } : default;
|
||||
|
||||
public static InteractionRule Policy(JsonObject note, string rule)
|
||||
{
|
||||
if (note["interactionPolicy"] is not JsonObject policy || policy[rule] is not JsonObject allowed)
|
||||
return default;
|
||||
static List<string> Who(JsonNode node) => node switch
|
||||
{
|
||||
JsonArray array => array.Select(Id).Where(id => id != default).Take(MaxAudience).ToList(),
|
||||
JsonNode single when Id(single) is { } id => new List<string> { id },
|
||||
_ => new List<string>()
|
||||
};
|
||||
return new InteractionRule
|
||||
{
|
||||
Automatic = Who(allowed["automaticApproval"] ?? allowed["always"]),
|
||||
|
||||
Reference in new issue
Block a user