Split nip30303 compound metadata tags into per-field tags

The artifact/dialect/chapter/translation-version events packed several
independent attributes into single positional tags
(["artifact", url, visibility, license], ["dialect", name, country,
language], etc.). Positional packing made every field mandatory (a
missing or malformed field nulled the whole metadata blob), blocked
extension, and forced ArtifactMetadataTag and
TranslationArtifactVersionMetadataTag to share TAG_NAME "artifact" with
field 1 meaning url vs name.

Replace the four compound tags with seven shared single-field tags
(NameTag, UrlTag, VisibilityTag, LicenseTag, CountryTag, LanguageTag,
OriginalTextTag), following the NIP-23 one-tag-per-field convention.
Event accessors now read each field independently and build()/toXEvent()
emit one tag per field; from...Event() readers let-chain the per-field
accessors. This also removes the duplicate "artifact" tag-name collision.

Note: breaking wire-format change for kinds 30300/30302/30304/30306;
safe now since these events are not published yet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kgothatso NgakoandClaude Opus 4.8 committed 2026-07-26 00:06:12 +02:00
1 parent c45a310641
commit 8e3c1cffe2
19 files changed
+276 -288

No files matched your search

@@ -11,8 +11,10 @@ import com.vitorpamplona.quartz.nip31Alts.AltTag
import press.mantra.compose.database.model.traits.OptionalNostrEventEntity import press.mantra.compose.database.model.traits.OptionalNostrEventEntity
import press.mantra.compose.database.model.traits.TimestampedEntity import press.mantra.compose.database.model.traits.TimestampedEntity
import press.mantra.compose.nostr.nip30303.ArtifactEvent import press.mantra.compose.nostr.nip30303.ArtifactEvent
import press.mantra.compose.nostr.nip30303.tags.ArtifactMetadataTag
import press.mantra.compose.nostr.nip30303.tags.DialectIdTag import press.mantra.compose.nostr.nip30303.tags.DialectIdTag
import press.mantra.compose.nostr.nip30303.tags.LicenseTag
import press.mantra.compose.nostr.nip30303.tags.UrlTag
import press.mantra.compose.nostr.nip30303.tags.VisibilityTag
import kotlin.time.Clock import kotlin.time.Clock
import kotlin.time.Instant import kotlin.time.Instant
@@ -69,13 +71,9 @@ data class MantraArtifact(
pubKey = publicKey, pubKey = publicKey,
createdAt = createdAt.epochSeconds, createdAt = createdAt.epochSeconds,
tags = TagArrayBuilder<ArtifactEvent>() tags = TagArrayBuilder<ArtifactEvent>()
.addUnique( .addUnique(UrlTag.assemble(url))
ArtifactMetadataTag.assemble( .addUnique(VisibilityTag.assemble(visibility))
url = url, .addUnique(LicenseTag.assemble(license))
visibility = visibility,
license = license
)
)
.addUnique( .addUnique(
DialectIdTag.assemble(dialectId) DialectIdTag.assemble(dialectId)
) )
@@ -109,20 +107,24 @@ data class MantraArtifact(
) )
} }
fun fromArtifactEvent(artifactEvent: ArtifactEvent, chatRoomId: HexKey, ): MantraArtifact? { fun fromArtifactEvent(artifactEvent: ArtifactEvent, chatRoomId: HexKey, ): MantraArtifact? {
return artifactEvent.artifactMetadata?.let { artifactMetadata -> return artifactEvent.url()?.let { url ->
artifactEvent.dialectId()?.let { dialectId -> artifactEvent.visibility()?.let { visibility ->
MantraArtifact( artifactEvent.license()?.let { license ->
id = artifactEvent.id, artifactEvent.dialectId()?.let { dialectId ->
publicKey = artifactEvent.pubKey, MantraArtifact(
dialectId = dialectId, id = artifactEvent.id,
createdAt = Instant.fromEpochSeconds(artifactEvent.createdAt), publicKey = artifactEvent.pubKey,
url = artifactMetadata.url, dialectId = dialectId,
license = artifactMetadata.license, createdAt = Instant.fromEpochSeconds(artifactEvent.createdAt),
visibility = artifactMetadata.visibility, url = url,
name = artifactEvent.content, license = license,
signature = artifactEvent.sig, visibility = visibility,
chatRoomId = chatRoomId name = artifactEvent.content,
) signature = artifactEvent.sig,
chatRoomId = chatRoomId
)
}
}
} }
} }
} }
@@ -10,8 +10,9 @@ import press.mantra.compose.database.model.traits.TimestampedEntity
import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent
import press.mantra.compose.nostr.nip30303.ChapterEvent import press.mantra.compose.nostr.nip30303.ChapterEvent
import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag
import press.mantra.compose.nostr.nip30303.tags.ChapterMetadataTag
import press.mantra.compose.nostr.nip30303.tags.IndexTag import press.mantra.compose.nostr.nip30303.tags.IndexTag
import press.mantra.compose.nostr.nip30303.tags.NameTag
import press.mantra.compose.nostr.nip30303.tags.OriginalTextTag
import press.mantra.compose.nostr.nip30303.tags.WordStatisticsTag import press.mantra.compose.nostr.nip30303.tags.WordStatisticsTag
import kotlin.time.Clock import kotlin.time.Clock
import kotlin.time.Instant import kotlin.time.Instant
@@ -74,12 +75,8 @@ data class MantraChapter(
.addUnique( .addUnique(
ArtifactVersionIdTag.assemble(artifactVersionId) ArtifactVersionIdTag.assemble(artifactVersionId)
) )
.addUnique( .addUnique(NameTag.assemble(name))
ChapterMetadataTag.assemble( .addUnique(OriginalTextTag.assemble(originalText))
name = name,
originalText = originalText,
)
)
.addUnique( .addUnique(
IndexTag.assemble( IndexTag.assemble(
index index
@@ -96,23 +93,25 @@ data class MantraChapter(
companion object { companion object {
fun fromChapterEvent(chapterEvent: ChapterEvent, chatRoomId: HexKey): MantraChapter? { fun fromChapterEvent(chapterEvent: ChapterEvent, chatRoomId: HexKey): MantraChapter? {
return chapterEvent.chapterMetadata?.let { chapterMetadata -> return chapterEvent.name()?.let { name ->
chapterEvent.wordStatisticsTag?.let { wordStatisticsTag -> chapterEvent.originalText()?.let { originalText ->
chapterEvent.artifactVersionId()?.let { artifactId -> chapterEvent.wordStatisticsTag?.let { wordStatisticsTag ->
chapterEvent.index()?.let { index -> chapterEvent.artifactVersionId()?.let { artifactId ->
MantraChapter( chapterEvent.index()?.let { index ->
id = chapterEvent.id, MantraChapter(
publicKey = chapterEvent.pubKey, id = chapterEvent.id,
createdAt = Instant.fromEpochSeconds(chapterEvent.createdAt), publicKey = chapterEvent.pubKey,
artifactVersionId = artifactId, createdAt = Instant.fromEpochSeconds(chapterEvent.createdAt),
name = chapterMetadata.name, artifactVersionId = artifactId,
originalText = chapterMetadata.originalText, name = name,
index = index, originalText = originalText,
wordCount = wordStatisticsTag.wordCount, index = index,
characterCount = wordStatisticsTag.characterCount, wordCount = wordStatisticsTag.wordCount,
signature = chapterEvent.sig, characterCount = wordStatisticsTag.characterCount,
chatRoomId = chatRoomId signature = chapterEvent.sig,
) chatRoomId = chatRoomId
)
}
} }
} }
} }
@@ -10,7 +10,9 @@ import press.mantra.compose.database.model.traits.TimestampedEntity
import press.mantra.compose.nostr.nip30303.ChunkEvent import press.mantra.compose.nostr.nip30303.ChunkEvent
import press.mantra.compose.nostr.nip30303.DialectEvent import press.mantra.compose.nostr.nip30303.DialectEvent
import press.mantra.compose.nostr.nip30303.tags.ChapterIdTag import press.mantra.compose.nostr.nip30303.tags.ChapterIdTag
import press.mantra.compose.nostr.nip30303.tags.DialectMetadataTag import press.mantra.compose.nostr.nip30303.tags.CountryTag
import press.mantra.compose.nostr.nip30303.tags.LanguageTag
import press.mantra.compose.nostr.nip30303.tags.NameTag
import kotlin.time.Clock import kotlin.time.Clock
import kotlin.time.Instant import kotlin.time.Instant
@@ -56,13 +58,9 @@ data class MantraDialect(
pubKey = publicKey, pubKey = publicKey,
createdAt = createdAt.epochSeconds, createdAt = createdAt.epochSeconds,
tags = TagArrayBuilder<ChunkEvent>() tags = TagArrayBuilder<ChunkEvent>()
.addUnique( .addUnique(NameTag.assemble(name))
DialectMetadataTag.assemble( .addUnique(CountryTag.assemble(country))
name = name, .addUnique(LanguageTag.assemble(language))
country = country,
language = language
)
)
.build(), .build(),
content = language, // TODO: Consider using the isoCode... as content? content = language, // TODO: Consider using the isoCode... as content?
sig = signature sig = signature
@@ -11,7 +11,9 @@ import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent
import press.mantra.compose.nostr.nip30303.TranslationArtifactVersionEvent import press.mantra.compose.nostr.nip30303.TranslationArtifactVersionEvent
import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag
import press.mantra.compose.nostr.nip30303.tags.DialectIdTag import press.mantra.compose.nostr.nip30303.tags.DialectIdTag
import press.mantra.compose.nostr.nip30303.tags.TranslationArtifactVersionMetadataTag import press.mantra.compose.nostr.nip30303.tags.LicenseTag
import press.mantra.compose.nostr.nip30303.tags.NameTag
import press.mantra.compose.nostr.nip30303.tags.VisibilityTag
import kotlin.time.Clock import kotlin.time.Clock
import kotlin.time.Instant import kotlin.time.Instant
@@ -80,13 +82,9 @@ data class MantraTranslationArtifactVersion(
.addUnique( .addUnique(
DialectIdTag.assemble(dialectId) DialectIdTag.assemble(dialectId)
) )
.addUnique( .addUnique(NameTag.assemble(name))
TranslationArtifactVersionMetadataTag.assemble( .addUnique(VisibilityTag.assemble(visibility))
name = name, .addUnique(LicenseTag.assemble(license))
visibility = visibility,
license = license
)
)
.build(), .build(),
content = "", content = "",
sig = signature sig = signature
@@ -98,19 +96,23 @@ data class MantraTranslationArtifactVersion(
return translationArtifactVersionEvent.artifactVersionId()?.let { artifactVersionId -> return translationArtifactVersionEvent.artifactVersionId()?.let { artifactVersionId ->
translationArtifactVersionEvent.dialectId()?.let { dialectId -> translationArtifactVersionEvent.dialectId()?.let { dialectId ->
translationArtifactVersionEvent.translationArtifactVersionMetadata?.let { translationArtifactVersionMetadata -> translationArtifactVersionEvent.name()?.let { name ->
MantraTranslationArtifactVersion( translationArtifactVersionEvent.visibility()?.let { visibility ->
id = translationArtifactVersionEvent.id, translationArtifactVersionEvent.license()?.let { license ->
publicKey = translationArtifactVersionEvent.pubKey, MantraTranslationArtifactVersion(
createdAt = Instant.fromEpochSeconds(translationArtifactVersionEvent.createdAt), id = translationArtifactVersionEvent.id,
artifactVersionId = artifactVersionId, publicKey = translationArtifactVersionEvent.pubKey,
dialectId = dialectId, createdAt = Instant.fromEpochSeconds(translationArtifactVersionEvent.createdAt),
name = translationArtifactVersionMetadata.name, artifactVersionId = artifactVersionId,
visibility = translationArtifactVersionMetadata.visibility, dialectId = dialectId,
license = translationArtifactVersionMetadata.license, name = name,
signature = translationArtifactVersionEvent.sig, visibility = visibility,
chatRoomId = chatRoomId license = license,
) signature = translationArtifactVersionEvent.sig,
chatRoomId = chatRoomId
)
}
}
} }
} }
} }
@@ -9,8 +9,10 @@ import com.vitorpamplona.quartz.nip22Comments.RootScope
import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.nip31Alts.alt
import com.vitorpamplona.quartz.nip50Search.SearchableEvent import com.vitorpamplona.quartz.nip50Search.SearchableEvent
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import press.mantra.compose.nostr.nip30303.tags.ArtifactMetadataTag
import press.mantra.compose.nostr.nip30303.tags.DialectIdTag import press.mantra.compose.nostr.nip30303.tags.DialectIdTag
import press.mantra.compose.nostr.nip30303.tags.LicenseTag
import press.mantra.compose.nostr.nip30303.tags.UrlTag
import press.mantra.compose.nostr.nip30303.tags.VisibilityTag
@Immutable @Immutable
@@ -22,11 +24,9 @@ class ArtifactEvent(
content: String, content: String,
sig: HexKey, sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) { ) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
val artifactMetadata = tags.firstNotNullOfOrNull(ArtifactMetadataTag::parse) fun url() = tags.firstNotNullOfOrNull(UrlTag::parse)?.url
fun visibility() = tags.firstNotNullOfOrNull(VisibilityTag::parse)?.visibility
fun url() = artifactMetadata?.url fun license() = tags.firstNotNullOfOrNull(LicenseTag::parse)?.license
fun visibility() = artifactMetadata?.visibility
fun license() = artifactMetadata?.license
fun dialectIdReference() = tags.firstNotNullOfOrNull(DialectIdTag::parse)?.ref fun dialectIdReference() = tags.firstNotNullOfOrNull(DialectIdTag::parse)?.ref
fun dialectId() = dialectIdReference()?.eventId fun dialectId() = dialectIdReference()?.eventId
@@ -45,13 +45,9 @@ class ArtifactEvent(
initializer: TagArrayBuilder<ArtifactEvent>.() -> Unit = {}, initializer: TagArrayBuilder<ArtifactEvent>.() -> Unit = {},
) = eventTemplate(KIND, name, createdAt) { ) = eventTemplate(KIND, name, createdAt) {
alt(ALT_DESCRIPTION) alt(ALT_DESCRIPTION)
addUnique( addUnique(UrlTag.assemble(url))
ArtifactMetadataTag.assemble( addUnique(VisibilityTag.assemble(visibility))
url = url, addUnique(LicenseTag.assemble(license))
visibility = visibility,
license = license
)
)
addUnique( addUnique(
DialectIdTag.assemble(dialectId) DialectIdTag.assemble(dialectId)
) )
@@ -8,8 +8,9 @@ import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.nip31Alts.alt
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag
import press.mantra.compose.nostr.nip30303.tags.ChapterMetadataTag
import press.mantra.compose.nostr.nip30303.tags.IndexTag import press.mantra.compose.nostr.nip30303.tags.IndexTag
import press.mantra.compose.nostr.nip30303.tags.NameTag
import press.mantra.compose.nostr.nip30303.tags.OriginalTextTag
import press.mantra.compose.nostr.nip30303.tags.WordStatisticsTag import press.mantra.compose.nostr.nip30303.tags.WordStatisticsTag
@@ -22,14 +23,13 @@ class ChapterEvent(
content: String, content: String,
sig: HexKey, sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) { ) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
val chapterMetadata = tags.firstNotNullOfOrNull(ChapterMetadataTag::parse)
val wordStatisticsTag = tags.firstNotNullOfOrNull(WordStatisticsTag::parse) val wordStatisticsTag = tags.firstNotNullOfOrNull(WordStatisticsTag::parse)
fun artifactVersionIdReference() = tags.firstNotNullOfOrNull(ArtifactVersionIdTag::parse)?.ref fun artifactVersionIdReference() = tags.firstNotNullOfOrNull(ArtifactVersionIdTag::parse)?.ref
fun artifactVersionId() = artifactVersionIdReference()?.eventId fun artifactVersionId() = artifactVersionIdReference()?.eventId
fun name() = chapterMetadata?.name fun name() = tags.firstNotNullOfOrNull(NameTag::parse)?.name
fun originalText() = chapterMetadata?.originalText fun originalText() = tags.firstNotNullOfOrNull(OriginalTextTag::parse)?.originalText
fun index() = tags.firstNotNullOfOrNull(IndexTag::parse)?.index fun index() = tags.firstNotNullOfOrNull(IndexTag::parse)?.index
fun wordCount() = wordStatisticsTag?.wordCount fun wordCount() = wordStatisticsTag?.wordCount
@@ -9,7 +9,9 @@ import com.vitorpamplona.quartz.nip22Comments.RootScope
import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.nip31Alts.alt
import com.vitorpamplona.quartz.nip50Search.SearchableEvent import com.vitorpamplona.quartz.nip50Search.SearchableEvent
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import press.mantra.compose.nostr.nip30303.tags.DialectMetadataTag import press.mantra.compose.nostr.nip30303.tags.CountryTag
import press.mantra.compose.nostr.nip30303.tags.LanguageTag
import press.mantra.compose.nostr.nip30303.tags.NameTag
@Immutable @Immutable
@@ -21,11 +23,9 @@ class DialectEvent(
content: String, content: String,
sig: HexKey, sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) { ) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
val dialectMetadata = tags.firstNotNullOfOrNull(DialectMetadataTag::parse) fun name() = tags.firstNotNullOfOrNull(NameTag::parse)?.name
fun country() = tags.firstNotNullOfOrNull(CountryTag::parse)?.country
fun name() = dialectMetadata?.name fun language() = tags.firstNotNullOfOrNull(LanguageTag::parse)?.language
fun country() = dialectMetadata?.country
fun language() = dialectMetadata?.language
companion object { companion object {
const val KIND = 30304 const val KIND = 30304
@@ -9,7 +9,9 @@ import com.vitorpamplona.quartz.nip31Alts.alt
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag import press.mantra.compose.nostr.nip30303.tags.ArtifactVersionIdTag
import press.mantra.compose.nostr.nip30303.tags.DialectIdTag import press.mantra.compose.nostr.nip30303.tags.DialectIdTag
import press.mantra.compose.nostr.nip30303.tags.TranslationArtifactVersionMetadataTag import press.mantra.compose.nostr.nip30303.tags.LicenseTag
import press.mantra.compose.nostr.nip30303.tags.NameTag
import press.mantra.compose.nostr.nip30303.tags.VisibilityTag
@Immutable @Immutable
@@ -22,7 +24,9 @@ class TranslationArtifactVersionEvent(
sig: HexKey, sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) { ) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
val translationArtifactVersionMetadata = tags.firstNotNullOfOrNull(TranslationArtifactVersionMetadataTag::parse) fun name() = tags.firstNotNullOfOrNull(NameTag::parse)?.name
fun visibility() = tags.firstNotNullOfOrNull(VisibilityTag::parse)?.visibility
fun license() = tags.firstNotNullOfOrNull(LicenseTag::parse)?.license
fun artifactVersionIdReference() = tags.firstNotNullOfOrNull(ArtifactVersionIdTag::parse)?.ref fun artifactVersionIdReference() = tags.firstNotNullOfOrNull(ArtifactVersionIdTag::parse)?.ref
fun artifactVersionId() = artifactVersionIdReference()?.eventId fun artifactVersionId() = artifactVersionIdReference()?.eventId
@@ -1,49 +0,0 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class ArtifactMetadataTag(
val url: String,
val visibility: String,
val license: String,
) {
fun toTagArray() = assemble(
url = url,
visibility = visibility,
license = license
)
companion object {
const val TAG_NAME = "artifact"
fun parse(tag: Array<String>): ArtifactMetadataTag? {
ensure(tag.has(3)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return ArtifactMetadataTag(
url = tag[1],
visibility = tag[2],
license = tag[3],
)
}
fun assemble(
url: String,
visibility: String,
license: String,
): Array<String> = arrayOf(
TAG_NAME,
url,
visibility,
license
)
fun assemble(artifactMetadataTag: ArtifactMetadataTag) = assemble(
url = artifactMetadataTag.url,
visibility = artifactMetadataTag.visibility,
license = artifactMetadataTag.license
)
}
}
@@ -1,42 +0,0 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class ChapterMetadataTag(
val name: String,
val originalText: String,
) {
fun toTagArray() = assemble(
name = name,
originalText = originalText,
)
companion object {
const val TAG_NAME = "chapter"
fun parse(tag: Array<String>): ChapterMetadataTag? {
ensure(tag.has(2)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return ChapterMetadataTag(
name = tag[1],
originalText = tag[2],
)
}
fun assemble(
name: String,
originalText: String,
): Array<String> = arrayOf(
TAG_NAME,
name,
originalText,
)
fun assemble(chapterMetadataTag: ChapterMetadataTag) = assemble(
name = chapterMetadataTag.name,
originalText = chapterMetadataTag.originalText,
)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class CountryTag(
val country: String,
) {
fun toTagArray() = assemble(country = country)
companion object {
const val TAG_NAME = "country"
fun parse(tag: Array<String>): CountryTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return CountryTag(country = tag[1])
}
fun assemble(country: String): Array<String> = arrayOf(TAG_NAME, country)
fun assemble(countryTag: CountryTag) = assemble(country = countryTag.country)
}
}
@@ -1,48 +0,0 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class DialectMetadataTag(
val name: String,
val country: String,
val language: String,
) {
fun toTagArray() = assemble(
name = name,
country = country,
language = language
)
companion object {
const val TAG_NAME = "dialect"
fun parse(tag: Array<String>): DialectMetadataTag? {
ensure(tag.has(3)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return DialectMetadataTag(
name = tag[1],
country = tag[2],
language = tag[3],
)
}
fun assemble(
name: String,
country: String,
language: String,
): Array<String> = arrayOf(
TAG_NAME,
name,
country,
language
)
fun assemble(dialectMetadataTag: DialectMetadataTag) = assemble(
name = dialectMetadataTag.name,
country = dialectMetadataTag.country,
language = dialectMetadataTag.language
)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class LanguageTag(
val language: String,
) {
fun toTagArray() = assemble(language = language)
companion object {
const val TAG_NAME = "language"
fun parse(tag: Array<String>): LanguageTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return LanguageTag(language = tag[1])
}
fun assemble(language: String): Array<String> = arrayOf(TAG_NAME, language)
fun assemble(languageTag: LanguageTag) = assemble(language = languageTag.language)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class LicenseTag(
val license: String,
) {
fun toTagArray() = assemble(license = license)
companion object {
const val TAG_NAME = "license"
fun parse(tag: Array<String>): LicenseTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return LicenseTag(license = tag[1])
}
fun assemble(license: String): Array<String> = arrayOf(TAG_NAME, license)
fun assemble(licenseTag: LicenseTag) = assemble(license = licenseTag.license)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class NameTag(
val name: String,
) {
fun toTagArray() = assemble(name = name)
companion object {
const val TAG_NAME = "name"
fun parse(tag: Array<String>): NameTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return NameTag(name = tag[1])
}
fun assemble(name: String): Array<String> = arrayOf(TAG_NAME, name)
fun assemble(nameTag: NameTag) = assemble(name = nameTag.name)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class OriginalTextTag(
val originalText: String,
) {
fun toTagArray() = assemble(originalText = originalText)
companion object {
const val TAG_NAME = "original_text"
fun parse(tag: Array<String>): OriginalTextTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return OriginalTextTag(originalText = tag[1])
}
fun assemble(originalText: String): Array<String> = arrayOf(TAG_NAME, originalText)
fun assemble(originalTextTag: OriginalTextTag) = assemble(originalText = originalTextTag.originalText)
}
}
@@ -1,49 +0,0 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class TranslationArtifactVersionMetadataTag(
val name: String,
val visibility: String,
val license: String,
) {
fun toTagArray() = assemble(
name = name,
visibility = visibility,
license = license
)
companion object {
const val TAG_NAME = "artifact"
fun parse(tag: Array<String>): TranslationArtifactVersionMetadataTag? {
ensure(tag.has(3)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return TranslationArtifactVersionMetadataTag(
name = tag[1],
visibility = tag[2],
license = tag[3],
)
}
fun assemble(
name: String,
visibility: String,
license: String,
): Array<String> = arrayOf(
TAG_NAME,
name,
visibility,
license
)
fun assemble(translationArtifactVersionMetadataTag: TranslationArtifactVersionMetadataTag) = assemble(
name = translationArtifactVersionMetadataTag.name,
visibility = translationArtifactVersionMetadataTag.visibility,
license = translationArtifactVersionMetadataTag.license
)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class UrlTag(
val url: String,
) {
fun toTagArray() = assemble(url = url)
companion object {
const val TAG_NAME = "url"
fun parse(tag: Array<String>): UrlTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return UrlTag(url = tag[1])
}
fun assemble(url: String): Array<String> = arrayOf(TAG_NAME, url)
fun assemble(urlTag: UrlTag) = assemble(url = urlTag.url)
}
}
@@ -0,0 +1,25 @@
package press.mantra.compose.nostr.nip30303.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
class VisibilityTag(
val visibility: String,
) {
fun toTagArray() = assemble(visibility = visibility)
companion object {
const val TAG_NAME = "visibility"
fun parse(tag: Array<String>): VisibilityTag? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return VisibilityTag(visibility = tag[1])
}
fun assemble(visibility: String): Array<String> = arrayOf(TAG_NAME, visibility)
fun assemble(visibilityTag: VisibilityTag) = assemble(visibility = visibilityTag.visibility)
}
}