mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 11:18:24 +00:00
feat(home): request pictures and every NIP-71 video kind on all home legs
The "All Follows" home feed fans out to four REQ builders — authors, hashtags, geohashes and communities. Only the authors leg asked for pictures (kind 20) and the NIP-71 videos (21, 22, 34235, 34236); the other three stopped at text notes, articles, classifieds, highlights, wiki and friends. HomeNewThreadFeedFilter already accepts all of those kinds, and AllFollowsTopNavFilter.match() already matches an event by a followed hashtag, geohash or community, so the events would have rendered fine — they were simply never requested. A kind-22 short tagged #bitcoin never reached Home while a kind-1 with the same tag did. Adds the five media kinds to HomePostsBuHashtagsKinds, HomePostsByGeohashKinds and HomePostsFromCommunityKinds, and derives HomePostsFromCommunityKindsStr (the `k` tag values on a NIP-72 post approval) from the kind list instead of repeating it by hand, so the two cannot drift apart again. Kinds 34235/34236 are current NIP-71 kinds, not deprecated ones — drops the "legacy" framing from the comments that described them that way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019V3yENZpF2eTDSzjnj1ZCi
This commit is contained in:
+3
-3
@@ -186,7 +186,7 @@ class NostrSignerPermissionLedger(
|
||||
* delete afterwards, in the same risk class as the original kind 1/6/7 set (notes, reposts,
|
||||
* reactions, pictures, videos, voice, public/live/relay chat, threads, polls, comments,
|
||||
* highlights, code snippets, file metadata, reports, torrents, long-form articles, wiki, status).
|
||||
* Some are *addressable* (long-form 30023, wiki 30818, legacy video 34235/34236): re-signing
|
||||
* Some are *addressable* (long-form 30023, wiki 30818, video 34235/34236): re-signing
|
||||
* with the same `d` tag replaces the app's own prior version at that address — an accepted
|
||||
* trade-off, since an app that can already post arbitrary notes could do equal reputational harm.
|
||||
* The set also includes two harmless non-content signatures:
|
||||
@@ -247,8 +247,8 @@ class NostrSignerPermissionLedger(
|
||||
LongTextNoteEvent.KIND, // 30023 — NIP-23 long-form articles (addressable content)
|
||||
StatusEvent.KIND, // 30315 — ephemeral user status / presence
|
||||
WikiNoteEvent.KIND, // 30818 — NIP-54 wiki articles (addressable content)
|
||||
VideoHorizontalEvent.KIND, // 34235 — legacy addressable horizontal video (NIP-71)
|
||||
VideoVerticalEvent.KIND, // 34236 — legacy addressable vertical video (NIP-71)
|
||||
VideoHorizontalEvent.KIND, // 34235 — addressable horizontal video (NIP-71)
|
||||
VideoVerticalEvent.KIND, // 34236 — addressable vertical video (NIP-71)
|
||||
PublicationIndexEvent.KIND, // 30040 — NKBIP-01 publication index (addressable content)
|
||||
LearningResourceEvent.KIND, // 30142 — learning resources (addressable content)
|
||||
BlossomPieceIndexEvent.KIND, // 32176 — Blossom piece indexes (addressable content)
|
||||
|
||||
+10
@@ -35,6 +35,11 @@ import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoHorizontalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoNormalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoShortEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoVerticalEvent
|
||||
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||
import com.vitorpamplona.quartz.nip99Classifieds.ClassifiedsEvent
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
|
||||
@@ -52,6 +57,11 @@ val HomePostsByGeohashKinds =
|
||||
VoiceEvent.KIND,
|
||||
AttestationEvent.KIND,
|
||||
InteractiveStoryPrologueEvent.KIND,
|
||||
PictureEvent.KIND,
|
||||
VideoNormalEvent.KIND,
|
||||
VideoShortEvent.KIND,
|
||||
VideoHorizontalEvent.KIND,
|
||||
VideoVerticalEvent.KIND,
|
||||
)
|
||||
|
||||
fun filterHomePostsByGeohashes(
|
||||
|
||||
+10
@@ -38,6 +38,11 @@ import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoHorizontalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoNormalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoShortEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoVerticalEvent
|
||||
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||
import com.vitorpamplona.quartz.nip99Classifieds.ClassifiedsEvent
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
|
||||
@@ -57,6 +62,11 @@ val HomePostsBuHashtagsKinds =
|
||||
VoiceEvent.KIND,
|
||||
AttestationEvent.KIND,
|
||||
InteractiveStoryPrologueEvent.KIND,
|
||||
PictureEvent.KIND,
|
||||
VideoNormalEvent.KIND,
|
||||
VideoShortEvent.KIND,
|
||||
VideoHorizontalEvent.KIND,
|
||||
VideoVerticalEvent.KIND,
|
||||
)
|
||||
|
||||
fun filterHomePostsByHashtags(
|
||||
|
||||
+12
-13
@@ -32,6 +32,11 @@ import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoHorizontalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoNormalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoShortEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoVerticalEvent
|
||||
import com.vitorpamplona.quartz.nip72ModCommunities.approval.CommunityPostApprovalEvent
|
||||
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
||||
@@ -49,21 +54,15 @@ val HomePostsFromCommunityKinds =
|
||||
CommunityPostApprovalEvent.KIND,
|
||||
CommentEvent.KIND,
|
||||
InteractiveStoryPrologueEvent.KIND,
|
||||
PictureEvent.KIND,
|
||||
VideoNormalEvent.KIND,
|
||||
VideoShortEvent.KIND,
|
||||
VideoHorizontalEvent.KIND,
|
||||
VideoVerticalEvent.KIND,
|
||||
)
|
||||
|
||||
val HomePostsFromCommunityKindsStr =
|
||||
listOf(
|
||||
TextNoteEvent.KIND.toString(),
|
||||
LongTextNoteEvent.KIND.toString(),
|
||||
ClassifiedsEvent.KIND.toString(),
|
||||
HighlightEvent.KIND.toString(),
|
||||
PollEvent.KIND.toString(),
|
||||
WikiNoteEvent.KIND.toString(),
|
||||
NipTextEvent.KIND.toString(),
|
||||
CommunityPostApprovalEvent.KIND.toString(),
|
||||
CommentEvent.KIND.toString(),
|
||||
InteractiveStoryPrologueEvent.KIND.toString(),
|
||||
)
|
||||
/** The same set, as the `k` tag values a NIP-72 post approval carries. */
|
||||
val HomePostsFromCommunityKindsStr = HomePostsFromCommunityKinds.map { it.toString() }
|
||||
|
||||
fun filterHomePostsFromCommunity(
|
||||
relay: NormalizedRelayUrl,
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.relayClient.home
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.home.nip01Core.HomePostsBuHashtagsKinds
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.home.nip01Core.HomePostsByGeohashKinds
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.home.nip65Follows.HomePostsNewThreadKinds1
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.home.nip72Communities.HomePostsFromCommunityKinds
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.home.nip72Communities.HomePostsFromCommunityKindsStr
|
||||
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoHorizontalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoNormalEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoShortEvent
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoVerticalEvent
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* The "All Follows" home feed fans out to four REQ builders: authors, hashtags, geohashes and
|
||||
* communities. The home DAL renders pictures and every NIP-71 video kind from any of those legs,
|
||||
* so a leg that omits a media kind silently hides content the feed would happily show — a
|
||||
* kind-22 short tagged `#bitcoin` never arriving while a kind-1 with the same tag does.
|
||||
*/
|
||||
class HomeMediaKindCoverageTest {
|
||||
private val mediaKinds =
|
||||
listOf(
|
||||
PictureEvent.KIND,
|
||||
VideoNormalEvent.KIND,
|
||||
VideoShortEvent.KIND,
|
||||
VideoHorizontalEvent.KIND,
|
||||
VideoVerticalEvent.KIND,
|
||||
)
|
||||
|
||||
private fun assertCarriesMedia(
|
||||
legName: String,
|
||||
kinds: List<Int>,
|
||||
) = mediaKinds.forEach {
|
||||
assertTrue(it in kinds, "$legName must request kind $it")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun everyHomeLegRequestsPicturesAndAllVideoKinds() {
|
||||
assertCarriesMedia("authors", HomePostsNewThreadKinds1)
|
||||
assertCarriesMedia("hashtags", HomePostsBuHashtagsKinds)
|
||||
assertCarriesMedia("geohashes", HomePostsByGeohashKinds)
|
||||
assertCarriesMedia("communities", HomePostsFromCommunityKinds)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun communityApprovalKTagsMirrorTheCommunityKinds() {
|
||||
assertEquals(HomePostsFromCommunityKinds.map { it.toString() }, HomePostsFromCommunityKindsStr)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
/**
|
||||
* Kinds 34235/34236 (legacy NIP-71 videos) are parameterized replaceable
|
||||
* Kinds 34235/34236 (the addressable NIP-71 videos) are parameterized replaceable
|
||||
* events: their address MUST include the `d` tag. A wrong (empty-dTag)
|
||||
* address makes LocalCache consume the event into a different
|
||||
* AddressableNote than the one `a` tags point to, so quotes/reposts of
|
||||
|
||||
Reference in New Issue
Block a user