NIP-30: fix EmojiPackEvent.build typing and add metadata helpers
The build DSL was typed as TagArrayBuilder<GitRepositoryEvent>, which made signer.sign(template) return the wrong event subclass. Retype it to EmojiPackEvent and add local TagArrayBuilder extensions for title, description, and image tags. Also add title()/description()/image() accessors on EmojiPackEvent to match the LabeledBookmarkListEvent pattern.
This commit is contained in:
+19
-5
@@ -26,9 +26,11 @@ import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.dTag.dTag
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.repository.name
|
||||
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
@@ -42,6 +44,18 @@ class EmojiPackEvent(
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : PrivateTagArrayEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
@Deprecated("NIP-51 has deprecated name. Use title instead", ReplaceWith("title()"))
|
||||
fun name() = tags.firstNotNullOfOrNull(NameTag::parse)
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun titleOrName() = title() ?: name()
|
||||
|
||||
fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||
|
||||
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||
|
||||
companion object {
|
||||
const val KIND = 30030
|
||||
const val ALT_DESCRIPTION = "Emoji pack"
|
||||
@@ -51,11 +65,11 @@ class EmojiPackEvent(
|
||||
name: String,
|
||||
dTag: String = Uuid.random().toString(),
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<GitRepositoryEvent>.() -> Unit = {},
|
||||
) = eventTemplate(KIND, "", createdAt) {
|
||||
initializer: TagArrayBuilder<EmojiPackEvent>.() -> Unit = {},
|
||||
) = eventTemplate<EmojiPackEvent>(KIND, "", createdAt) {
|
||||
alt(ALT_DESCRIPTION)
|
||||
dTag(dTag)
|
||||
name(name)
|
||||
title(name)
|
||||
initializer()
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.quartz.nip30CustomEmoji.pack
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||
|
||||
fun TagArrayBuilder<EmojiPackEvent>.title(title: String) = addUnique(TitleTag.assemble(title))
|
||||
|
||||
fun TagArrayBuilder<EmojiPackEvent>.description(listDescription: String) = addUnique(DescriptionTag.assemble(listDescription))
|
||||
|
||||
fun TagArrayBuilder<EmojiPackEvent>.image(url: String) = addUnique(ImageTag.assemble(url))
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.quartz.nip30CustomEmoji
|
||||
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.description
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.image
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class EmojiPackEventBuildTest {
|
||||
@Test
|
||||
fun buildIncludesTitleDTagAltAndEmojis() {
|
||||
val template =
|
||||
EmojiPackEvent.build(name = "My Pack", dTag = "my-pack") {
|
||||
description("A test pack")
|
||||
image("https://example.com/cover.jpg")
|
||||
emoji("smile", "https://example.com/smile.png")
|
||||
}
|
||||
|
||||
assertEquals(EmojiPackEvent.KIND, template.kind)
|
||||
assertEquals("", template.content)
|
||||
|
||||
val tagsByName = template.tags.groupBy { it[0] }
|
||||
assertTrue(tagsByName.containsKey("d"))
|
||||
assertEquals("my-pack", tagsByName["d"]!!.first()[1])
|
||||
assertTrue(tagsByName.containsKey("title"))
|
||||
assertEquals("My Pack", tagsByName["title"]!!.first()[1])
|
||||
assertTrue(tagsByName.containsKey("description"))
|
||||
assertEquals("A test pack", tagsByName["description"]!!.first()[1])
|
||||
assertTrue(tagsByName.containsKey("image"))
|
||||
assertEquals("https://example.com/cover.jpg", tagsByName["image"]!!.first()[1])
|
||||
assertTrue(tagsByName.containsKey("alt"))
|
||||
assertTrue(tagsByName.containsKey("emoji"))
|
||||
assertEquals("smile", tagsByName["emoji"]!!.first()[1])
|
||||
assertEquals("https://example.com/smile.png", tagsByName["emoji"]!!.first()[2])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emojiTagUsesEventTypedBuilder() {
|
||||
// Regression: EmojiPackEvent.build previously used TagArrayBuilder<GitRepositoryEvent>,
|
||||
// which caused callers to get a template of the wrong type. This test locks in the fix.
|
||||
val template = EmojiPackEvent.build(name = "test")
|
||||
assertEquals(EmojiPackEvent.KIND, template.kind)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun titleDescriptionImageAccessorsReadTags() {
|
||||
val event =
|
||||
EmojiPackEvent(
|
||||
id = "00",
|
||||
pubKey = "00",
|
||||
createdAt = 0L,
|
||||
tags =
|
||||
arrayOf(
|
||||
arrayOf("d", "mypack"),
|
||||
arrayOf("title", "My Pack"),
|
||||
arrayOf("description", "desc"),
|
||||
arrayOf("image", "https://example.com/cover.png"),
|
||||
arrayOf("emoji", "smile", "https://example.com/smile.png"),
|
||||
),
|
||||
content = "",
|
||||
sig = "00",
|
||||
)
|
||||
|
||||
assertEquals("My Pack", event.title())
|
||||
assertEquals("desc", event.description())
|
||||
assertEquals("https://example.com/cover.png", event.image())
|
||||
assertEquals("My Pack", event.titleOrName())
|
||||
assertEquals(1, event.taggedEmojis().size)
|
||||
assertEquals("smile", event.taggedEmojis().first().code)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user