A community's comments reach its microblog members
A comment in a community was announced only as Announce{Create}, which
Akkoma, Mastodon and Misskey drop: their members never saw it (the village
found Akkoma's missing). A comment is now also announced as itself, as a
new post already was; Lemmy answers that form 400, harmlessly. Nothing is
decided by the follower's software.
The town's checker expects a followers-only quote to stay with the
followers, and G-0003 covers only Lemmy-hosted communities (their relayed
moderation), since relayed likes count.
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
9268968fd4
commit
aecbf620a8
7 files changed
+34
-6
No files matched your search
@@ -90,6 +90,28 @@ namespace PrivaPub.Tests.Federation
|
||||
Assert.Contains(announces, a => a["object"] is JsonValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_comment_in_a_community_is_announced_activity_and_object_too()
|
||||
{
|
||||
var (_, owner) = await _harness.Persona("owner");
|
||||
var (_, community) = await Group(GroupKind.Community, PostingPolicy.Followers, owner.Id);
|
||||
var lemmy = new RemoteActor(_harness.Peer, "lemmy");
|
||||
var akkoma = new RemoteActor(_harness.Peer, "akkoma");
|
||||
await _harness.FollowedBy(community, lemmy);
|
||||
await _harness.FollowedBy(community, akkoma);
|
||||
var thread = Create(lemmy, new[] { community.Uri, Addressing.Public }, community.Uri);
|
||||
await _harness.Deliver(lemmy, "/human-centipede", thread);
|
||||
var comment = Create(lemmy, new[] { community.Uri, Addressing.Public }, community.Uri);
|
||||
comment["object"]!["inReplyTo"] = thread["object"]!["id"]!.GetValue<string>();
|
||||
|
||||
await _harness.Deliver(lemmy, "/human-centipede", comment);
|
||||
|
||||
var commentId = comment["object"]!["id"]!.GetValue<string>();
|
||||
var announces = (await _harness.Outgoing(akkoma.SharedInbox)).Where(a => a["actor"]!.GetValue<string>() == community.Uri).ToList();
|
||||
Assert.Contains(announces, a => a["object"] is JsonObject inner && inner["object"]?["id"]?.GetValue<string>() == commentId);
|
||||
Assert.Contains(announces, a => a["object"] is JsonValue bare && bare.GetValue<string>() == commentId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task An_open_community_takes_posts_from_anyone()
|
||||
{
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace PrivaPub.Domain.Statuses
|
||||
if (create != default)
|
||||
await _outbox.Publish(author, post, create, token);
|
||||
if (create != default && group is { IsCircle: false } && visibility is PostVisibility.Public or PostVisibility.Unlisted)
|
||||
await _groups.Announce(group, create, post.ObjectURI, isNewPost: string.IsNullOrEmpty(post.InReplyToURI), token);
|
||||
await _groups.Announce(group, create, post.ObjectURI, isNewPost: true, token);
|
||||
return new StatusOutcome(post);
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
if (conversation != default)
|
||||
await DB.Default.Update<DmGroup>().MatchID(conversation.ID).Modify(g => g.UpdatedAt, DateTime.UtcNow).ExecuteAsync(token);
|
||||
if (group is { IsCircle: false })
|
||||
await _groups.Announce(group, activity.AsObject(), note.Id, isNewPost: string.IsNullOrEmpty(note.InReplyTo), token);
|
||||
await _groups.Announce(group, activity.AsObject(), note.Id, isNewPost: true, token);
|
||||
}
|
||||
|
||||
async Task<bool> IsCircleMember(LocalActor circle, string actorUri, CancellationToken token) =>
|
||||
|
||||
@@ -67,6 +67,8 @@ namespace PrivaPub.Federation.Outbox
|
||||
// announces it back, and clears that before it answers the echo 400 ("Object is not remote").
|
||||
await _delivery.EnqueueToFollowers(group, announce, token);
|
||||
await Keep(group, announce, objectUri, token);
|
||||
// a new post or comment is also boosted as itself: microblogs (Mastodon, Akkoma, Misskey) drop an Announce of an
|
||||
// activity, so without it their members never see what is said in the community; Lemmy answers it 400, harmlessly
|
||||
if (isNewPost && !string.IsNullOrEmpty(objectUri))
|
||||
{
|
||||
var boost = ActivityPubRenderer.Announce(group, objectUri, $"announce-object-{key}");
|
||||
|
||||
+2
-1
@@ -297,7 +297,8 @@ Firefish is dead (its site has answered 410 since February 2025).
|
||||
- **Visibility:** Misskey recognises followers-only by the author's own `followers` URL, matched exactly. Otherwise:
|
||||
- **A "specified" (direct) note with no resolvable recipients that Misskey fetches by URL is stored as public.**
|
||||
Circle objects must therefore never be served to an unauthorised fetcher. They aren't: 404.
|
||||
- **Groups:** vanilla Misskey drops `Announce{Create}`, so groups should `Announce` the Note itself. We send both.
|
||||
- **Groups:** vanilla Misskey drops `Announce{Create}`, so groups should `Announce` the Note itself. We send both, for
|
||||
comments as for posts (Akkoma and Mastodon drop the activity form too; the town found Akkoma members missing them).
|
||||
- **Reactions:** must be `:name:` with no host, plus an Emoji tag, or they fall back to ❤.
|
||||
- **Article/Page titles** are never shown in Misskey's web UI.
|
||||
- **Iceshrimp.NET:**
|
||||
|
||||
@@ -114,7 +114,8 @@ class World:
|
||||
who |= self.follows.get(o["author"], set())
|
||||
if o.get("parent") and o["parent"] in self.objects:
|
||||
who.add(self.objects[o["parent"]]["author"])
|
||||
if o.get("quote") and o["quote"] in self.objects:
|
||||
# a quote reaches its quoted author when it is public or unlisted; a followers-only quote stays with the followers
|
||||
if o.get("quote") and o["quote"] in self.objects and v in ("public", "unlisted"):
|
||||
who.add(self.objects[o["quote"]]["author"])
|
||||
elif v == "circle":
|
||||
who |= self.members[o["group"]]
|
||||
|
||||
@@ -36,13 +36,15 @@
|
||||
"title": "Votes and moderation that a Lemmy community relays inside Announce (Like, Dislike, Undo, Delete, Block) are dropped",
|
||||
"match": {
|
||||
"feature": "count\\.like\\.community",
|
||||
"observer": "privapub"
|
||||
"observer": "privapub",
|
||||
"origin": "lemmy"
|
||||
},
|
||||
"kind": "server",
|
||||
"phase": "P7",
|
||||
"code": "PrivaPub/Federation/Inbox/Handlers/AnnounceHandler.cs:203",
|
||||
"opened": "2026-10-01",
|
||||
"status": "open"
|
||||
"status": "open",
|
||||
"note": "Relayed likes count since ed08f80; what stays open is moderation relayed by a Lemmy community (Delete, Block, Lock). Communities hosted here count their likes as any post does."
|
||||
},
|
||||
{
|
||||
"id": "G-0004",
|
||||
|
||||
Reference in new issue
Block a user