Filter thread replies to original author only
All checks were successful
CI / test (push) Successful in 45s

Only replies from the root post's author are rendered; replies from other
users are skipped. Adds fixture and test for a real-world post with an
other-author reply (3mhypinzezo2l).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-27 12:16:02 -03:00
parent 06067c0ff3
commit 3950a65783
3 changed files with 127 additions and 6 deletions

View File

@@ -174,6 +174,25 @@ class BlueskyThreadsTest extends TestCase {
$this->assertStringContainsString('View on Bluesky', $html);
}
/**
* A post with only a reply from another user (3mhypinzezo2l fixture) must
* render just the root post — the other-author reply is filtered out.
*/
public function testOtherAuthorRepliesAreExcluded(): void {
$data = json_decode(file_get_contents(__DIR__ . '/fixtures/thread_3mhypinzezo2l.json'), true);
$thread = $data['thread'];
$rootAuthorDid = $thread['post']['author']['did'];
$html = $this->call('renderThread', $thread, true, $rootAuthorDid);
$this->assertSame(1, substr_count($html, 'bsky-post'),
'Only the root post should be rendered; other-author reply must be excluded');
$this->assertSame(0, substr_count($html, 'bsky-replies'),
'No replies wrapper should be rendered when all replies are from other authors');
$this->assertStringNotContainsString('lasagnazero.bsky.social', $html,
'Reply author handle must not appear in output');
}
// -------------------------------------------------------------------------
// applyFacets — rich-text rendering
// -------------------------------------------------------------------------

View File

@@ -0,0 +1,93 @@
{
"thread": {
"$type": "app.bsky.feed.defs#threadViewPost",
"post": {
"uri": "at://did:plc:d4324t32vfi5xzydqbh2qdj3/app.bsky.feed.post/3mhypinzezo2l",
"cid": "bafyreialfdaqkwykiinxzy3xb6qhcenuwsaxi7d6qwzx4zfdyhprzo4s2e",
"author": {
"did": "did:plc:d4324t32vfi5xzydqbh2qdj3",
"handle": "hockeyviz.com",
"displayName": "Micah McCurdy ",
"avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:d4324t32vfi5xzydqbh2qdj3/bafkreiddyjdi3hty4z73vdoyxja3hj5n7izrsdmeoif2ppkqidbt4nsluq",
"associated": {
"chat": {
"allowIncoming": "all"
},
"activitySubscription": {
"allowSubscriptions": "followers"
}
},
"labels": [],
"createdAt": "2023-05-28T17:07:32.578Z"
},
"record": {
"$type": "app.bsky.feed.post",
"createdAt": "2026-03-26T23:01:26.959Z",
"facets": [],
"langs": [
"en"
],
"tags": [],
"text": "Any good musician can rerecord somebody else's song but what really makes a cover worth doing is that little note of jealousy nestled in the blanket of admiration. It's the same with reproving somebody else's result or redoing a viz. Shoulda been me, the grudgingist yet in fact highest respect."
},
"bookmarkCount": 0,
"replyCount": 1,
"repostCount": 0,
"likeCount": 21,
"quoteCount": 0,
"indexedAt": "2026-03-26T23:01:27.160Z",
"labels": []
},
"replies": [
{
"$type": "app.bsky.feed.defs#threadViewPost",
"post": {
"uri": "at://did:plc:vfi77nom5cwpnhurnxhy7ltj/app.bsky.feed.post/3mhyw2ijjc22a",
"cid": "bafyreif6evbxbqcf5t3t6i4apm6pertxy4mylleet6a2d2fgzwqnz6inly",
"author": {
"did": "did:plc:vfi77nom5cwpnhurnxhy7ltj",
"handle": "lasagnazero.bsky.social",
"displayName": "L0",
"avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:vfi77nom5cwpnhurnxhy7ltj/bafkreigjurbghqtq3iogsqarnxldhl54zqdmi657pflwrrqwa2wisteq6i",
"associated": {
"activitySubscription": {
"allowSubscriptions": "followers"
}
},
"labels": [],
"createdAt": "2024-11-07T14:26:50.985Z"
},
"record": {
"$type": "app.bsky.feed.post",
"createdAt": "2026-03-27T00:58:47.713Z",
"langs": [
"en",
"ru"
],
"reply": {
"parent": {
"cid": "bafyreialfdaqkwykiinxzy3xb6qhcenuwsaxi7d6qwzx4zfdyhprzo4s2e",
"uri": "at://did:plc:d4324t32vfi5xzydqbh2qdj3/app.bsky.feed.post/3mhypinzezo2l"
},
"root": {
"cid": "bafyreialfdaqkwykiinxzy3xb6qhcenuwsaxi7d6qwzx4zfdyhprzo4s2e",
"uri": "at://did:plc:d4324t32vfi5xzydqbh2qdj3/app.bsky.feed.post/3mhypinzezo2l"
}
},
"text": "Something about imitation and flattery\u2026"
},
"bookmarkCount": 0,
"replyCount": 0,
"repostCount": 0,
"likeCount": 0,
"quoteCount": 0,
"indexedAt": "2026-03-27T00:58:48.952Z",
"labels": []
},
"replies": [],
"threadContext": {}
}
],
"threadContext": {}
}
}