fix(ratings): show a user's own ratings and publications on their profile

A rating only reached its author's profile if somebody had reposted it. Both
profile gates were missing the kinds, so the events never arrived and would not
have been accepted if they had:

- `UserProfilePostKinds2` did not request 34259 or 30040, so the profile REQ
  never asked the author's outbox relays for them.
- `UserProfileNewThreadFeedFilter.acceptableEvent` did not accept either type.

The branch wired the Home feed's equivalent pair but not this one. The
addressable scan here has no kind allow-list of its own (unlike Home's
`ADDRESSABLE_KINDS`), so the DAL side is just the two type checks.

The rating check mirrors Home's: a rating with nothing to point at cannot be
rendered, so `hasTarget()` gates it rather than leaving an empty row on the
author's own profile.

Kinds deliberately left out: 30041 publication sections, because they are
chapters rather than posts and one book would bury a profile under 34 entries;
and 31987 relay reviews, which have the same shape as ratings but were never in
any feed and should be a decision of their own.

Verified on device against `npub1m4ny6...`, whose two ratings differ usefully:
the Wuthering Heights one has three kind-16 reposts and so was already visible,
while "Am Fluss der Zeiten" has none. The latter now renders on the profile as a
plain entry with no repost header, which it could only do by arriving through
these gates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wwk8tDEaEvsNoGbtrjZavz
This commit is contained in:
Vitor Pamplona
2026-09-08 11:09:05 -04:00
co-authored by Claude Opus 5
parent abc1caa666
commit b9165f421d
2 changed files with 11 additions and 1 deletions
@@ -41,6 +41,8 @@ import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStory
import com.vitorpamplona.quartz.experimental.music.playlist.MusicPlaylistEvent
import com.vitorpamplona.quartz.experimental.music.track.MusicTrackEvent
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
import com.vitorpamplona.quartz.experimental.publications.PublicationIndexEvent
import com.vitorpamplona.quartz.experimental.ratings.EntityRatingEvent
import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
@@ -107,7 +109,11 @@ class UserProfileNewThreadFeedFilter(
it.event is AttestationEvent ||
it.event is AttestationRequestEvent ||
it.event is AttestorRecommendationEvent ||
it.event is AttestorProficiencyEvent
it.event is AttestorProficiencyEvent ||
it.event is PublicationIndexEvent ||
// Mirrors the Home filter: a rating with nothing to point at cannot be
// rendered, so it would be an empty row on the author's own profile.
(it.event as? EntityRatingEvent)?.hasTarget() == true
) &&
it.isNewThread() &&
account.isAcceptable(it)
@@ -32,6 +32,8 @@ import com.vitorpamplona.quartz.experimental.birdstar.BirdDetectionEvent
import com.vitorpamplona.quartz.experimental.birdstar.BirdexEvent
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
import com.vitorpamplona.quartz.experimental.publications.PublicationIndexEvent
import com.vitorpamplona.quartz.experimental.ratings.EntityRatingEvent
import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
@@ -79,6 +81,8 @@ val UserProfilePostKinds2 =
AttestationEvent.KIND,
BirdDetectionEvent.KIND,
BirdexEvent.KIND,
EntityRatingEvent.KIND,
PublicationIndexEvent.KIND,
)
// NIP-5A nsites (15128/35128) and NIP-5D napplets (15129/35129) the user publishes, surfaced in