refactor: migrate NIP-58 badges to nip88Polls-style sub-package structure
Restructures the flat nip58Badges package into sub-packages following the established nip88Polls pattern with proper tag classes, TagArrayExt, and TagArrayBuilderExt for each event type: - definition/ - BadgeDefinitionEvent (kind 30009) with NameTag, ImageTag, DescriptionTag, ThumbTag supporting dimensions per spec - award/ - BadgeAwardEvent (kind 8) with build() method - profiles/ - BadgeProfilesEvent (kind 30008) with AcceptedBadge tag for proper paired a+e tag parsing per NIP-58 spec Adds build() companion methods to all three event types and full spec compliance including image/thumb dimension support. https://claude.ai/code/session_019Uvxfa7jJbjeprLxECoJ8s
This commit is contained in:
@@ -167,9 +167,9 @@ import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
|||||||
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.profiles.BadgeProfilesEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.WrappedEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.WrappedEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEve
|
|||||||
import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
|
import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
|
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.profiles.BadgeProfilesEvent
|
||||||
|
|
||||||
val FollowAndMutesFromKeyKinds =
|
val FollowAndMutesFromKeyKinds =
|
||||||
listOf(
|
listOf(
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ import com.vitorpamplona.quartz.nip52Calendar.appt.time.CalendarTimeSlotEvent
|
|||||||
import com.vitorpamplona.quartz.nip52Calendar.rsvp.CalendarRSVPEvent
|
import com.vitorpamplona.quartz.nip52Calendar.rsvp.CalendarRSVPEvent
|
||||||
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
||||||
import com.vitorpamplona.quartz.nip88Polls.response.PollResponseEvent
|
import com.vitorpamplona.quartz.nip88Polls.response.PollResponseEvent
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ import com.vitorpamplona.quartz.nip52Calendar.appt.day.CalendarDateSlotEvent
|
|||||||
import com.vitorpamplona.quartz.nip52Calendar.appt.time.CalendarTimeSlotEvent
|
import com.vitorpamplona.quartz.nip52Calendar.appt.time.CalendarTimeSlotEvent
|
||||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
|
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
||||||
|
|||||||
@@ -256,8 +256,8 @@ import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
|||||||
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.splits.hasZapSplitSetup
|
import com.vitorpamplona.quartz.nip57Zaps.splits.hasZapSplitSetup
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip64Chess.challenge.offer.LiveChessGameChallengeEvent
|
import com.vitorpamplona.quartz.nip64Chess.challenge.offer.LiveChessGameChallengeEvent
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonRow
|
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonRow
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BadgeDisplay(
|
fun BadgeDisplay(
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
|
|||||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.utils.Log
|
import com.vitorpamplona.quartz.utils.Log
|
||||||
import com.vitorpamplona.quartz.utils.flattenToSet
|
import com.vitorpamplona.quartz.utils.flattenToSet
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessa
|
|||||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
||||||
import com.vitorpamplona.quartz.nip71Video.VideoHorizontalEvent
|
import com.vitorpamplona.quartz.nip71Video.VideoHorizontalEvent
|
||||||
import com.vitorpamplona.quartz.nip71Video.VideoNormalEvent
|
import com.vitorpamplona.quartz.nip71Video.VideoNormalEvent
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
|||||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.profiles.BadgeProfilesEvent
|
||||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||||
|
|
||||||
val UserProfileMetadataKinds =
|
val UserProfileMetadataKinds =
|
||||||
|
|||||||
+3
-3
@@ -49,9 +49,9 @@ import com.vitorpamplona.amethyst.ui.stringRes
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.BadgePictureModifier
|
import com.vitorpamplona.amethyst.ui.theme.BadgePictureModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size35Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size35Modifier
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.profiles.BadgeProfilesEvent
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -232,9 +232,9 @@ import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
|||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.profiles.BadgeProfilesEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||||
import com.vitorpamplona.quartz.nip62RequestToVanish.RequestToVanishEvent
|
import com.vitorpamplona.quartz.nip62RequestToVanish.RequestToVanishEvent
|
||||||
|
|||||||
+1
-1
@@ -264,7 +264,7 @@ import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessa
|
|||||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.splits.hasZapSplitSetup
|
import com.vitorpamplona.quartz.nip57Zaps.splits.hasZapSplitSetup
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
|
|||||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
|
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
import com.vitorpamplona.quartz.nip84Highlights.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent
|
||||||
|
|||||||
+21
-8
@@ -18,20 +18,21 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* 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.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip58Badges
|
package com.vitorpamplona.quartz.nip58Badges.award
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
|
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
|
||||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
|
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
|
||||||
import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider
|
import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds
|
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
class BadgeAwardEvent(
|
class BadgeAwardEvent(
|
||||||
@@ -57,14 +58,26 @@ class BadgeAwardEvent(
|
|||||||
|
|
||||||
override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId)
|
override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId)
|
||||||
|
|
||||||
fun awardees() = taggedUsers()
|
fun awardees() = tags.awardees()
|
||||||
|
|
||||||
fun awardeeIds() = taggedUserIds()
|
fun awardeeIds() = tags.awardeeIds()
|
||||||
|
|
||||||
fun awardDefinition() = taggedAddresses()
|
fun awardDefinition() = tags.awardDefinitions()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val KIND = 8
|
const val KIND = 8
|
||||||
const val ALT = "Badge award"
|
const val ALT_DESCRIPTION = "Badge award"
|
||||||
|
|
||||||
|
fun build(
|
||||||
|
awardDefinition: ATag,
|
||||||
|
awardees: List<PTag>,
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<BadgeAwardEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, "", createdAt) {
|
||||||
|
alt(ALT_DESCRIPTION)
|
||||||
|
awardDefinition(awardDefinition)
|
||||||
|
awardees(awardees)
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.award
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.aTag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.people.pTag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.people.pTags
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeAwardEvent>.awardDefinition(tag: ATag) = aTag(tag)
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeAwardEvent>.awardees(tags: List<PTag>) = pTags(tags)
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeAwardEvent>.awardee(tag: PTag) = pTag(tag)
|
||||||
+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.nip58Badges.award
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArray
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||||
|
|
||||||
|
fun TagArray.awardees() = taggedUsers()
|
||||||
|
|
||||||
|
fun TagArray.awardeeIds() = taggedUserIds()
|
||||||
|
|
||||||
|
fun TagArray.awardDefinitions() = taggedAddresses()
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.definition
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
|
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.nip58Badges.definition.tags.ImageTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.ThumbTag
|
||||||
|
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class BadgeDefinitionEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: Array<Array<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey,
|
||||||
|
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||||
|
fun name() = tags.badgeName()
|
||||||
|
|
||||||
|
fun image() = tags.badgeImageUrl()
|
||||||
|
|
||||||
|
fun imageWithDimensions() = tags.badgeImage()
|
||||||
|
|
||||||
|
fun description() = tags.badgeDescription()
|
||||||
|
|
||||||
|
fun thumb() = tags.badgeThumbUrl()
|
||||||
|
|
||||||
|
fun thumbs() = tags.badgeThumbs()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KIND = 30009
|
||||||
|
const val ALT_DESCRIPTION = "Badge definition"
|
||||||
|
|
||||||
|
fun build(
|
||||||
|
badgeId: String,
|
||||||
|
name: String? = null,
|
||||||
|
image: ImageTag? = null,
|
||||||
|
description: String? = null,
|
||||||
|
thumbs: List<ThumbTag> = emptyList(),
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<BadgeDefinitionEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, "", createdAt) {
|
||||||
|
dTag(badgeId)
|
||||||
|
alt(ALT_DESCRIPTION)
|
||||||
|
name?.let { name(it) }
|
||||||
|
image?.let { image(it.url, it.dimensions) }
|
||||||
|
description?.let { description(it) }
|
||||||
|
if (thumbs.isNotEmpty()) {
|
||||||
|
thumbs(thumbs)
|
||||||
|
}
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(
|
||||||
|
badgeId: String,
|
||||||
|
name: String? = null,
|
||||||
|
imageUrl: String? = null,
|
||||||
|
imageDimensions: DimensionTag? = null,
|
||||||
|
description: String? = null,
|
||||||
|
thumbs: List<ThumbTag> = emptyList(),
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<BadgeDefinitionEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, "", createdAt) {
|
||||||
|
dTag(badgeId)
|
||||||
|
alt(ALT_DESCRIPTION)
|
||||||
|
name?.let { name(it) }
|
||||||
|
imageUrl?.let { image(it, imageDimensions) }
|
||||||
|
description?.let { description(it) }
|
||||||
|
if (thumbs.isNotEmpty()) {
|
||||||
|
thumbs(thumbs)
|
||||||
|
}
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.definition
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.DescriptionTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.ImageTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.NameTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.ThumbTag
|
||||||
|
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeDefinitionEvent>.name(name: String) = addUnique(NameTag.assemble(name))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeDefinitionEvent>.image(
|
||||||
|
url: String,
|
||||||
|
dimensions: DimensionTag? = null,
|
||||||
|
) = addUnique(ImageTag.assemble(url, dimensions))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeDefinitionEvent>.description(description: String) = addUnique(DescriptionTag.assemble(description))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeDefinitionEvent>.thumb(
|
||||||
|
url: String,
|
||||||
|
dimensions: DimensionTag? = null,
|
||||||
|
) = add(ThumbTag.assemble(url, dimensions))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeDefinitionEvent>.thumbs(thumbs: List<ThumbTag>) = addAll(ThumbTag.assemble(thumbs))
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.definition
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArray
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.DescriptionTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.ImageTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.NameTag
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.definition.tags.ThumbTag
|
||||||
|
|
||||||
|
fun TagArray.badgeName() = firstNotNullOfOrNull(NameTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.badgeImage() = firstNotNullOfOrNull(ImageTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.badgeImageUrl() = firstNotNullOfOrNull(ImageTag::parseUrl)
|
||||||
|
|
||||||
|
fun TagArray.badgeDescription() = firstNotNullOfOrNull(DescriptionTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.badgeThumbs() = mapNotNull(ThumbTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.badgeThumbUrl() = firstNotNullOfOrNull(ThumbTag::parseUrl)
|
||||||
+14
-23
@@ -18,31 +18,22 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* 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.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip58Badges
|
package com.vitorpamplona.quartz.nip58Badges.definition.tags
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
class BadgeDefinitionEvent(
|
|
||||||
id: HexKey,
|
|
||||||
pubKey: HexKey,
|
|
||||||
createdAt: Long,
|
|
||||||
tags: Array<Array<String>>,
|
|
||||||
content: String,
|
|
||||||
sig: HexKey,
|
|
||||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
|
||||||
fun name() = tags.firstOrNull { it.size > 1 && it[0] == "name" }?.get(1)
|
|
||||||
|
|
||||||
fun thumb() = tags.firstOrNull { it.size > 1 && it[0] == "thumb" }?.get(1)
|
|
||||||
|
|
||||||
fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1)
|
|
||||||
|
|
||||||
fun description() = tags.firstOrNull { it.size > 1 && it[0] == "description" }?.get(1)
|
|
||||||
|
|
||||||
|
class DescriptionTag {
|
||||||
companion object {
|
companion object {
|
||||||
const val KIND = 30009
|
const val TAG_NAME = "description"
|
||||||
const val ALT = "Badge definition"
|
|
||||||
|
fun parse(tag: Array<String>): String? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(description: String) = arrayOf(TAG_NAME, description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.definition.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
|
||||||
|
import com.vitorpamplona.quartz.utils.arrayOfNotNull
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class ImageTag(
|
||||||
|
val url: String,
|
||||||
|
val dimensions: DimensionTag? = null,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "image"
|
||||||
|
|
||||||
|
fun parse(tag: Array<String>): ImageTag? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
val dims = tag.getOrNull(2)?.let { DimensionTag.parse(it) }
|
||||||
|
return ImageTag(tag[1], dims)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseUrl(tag: Array<String>): String? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(
|
||||||
|
url: String,
|
||||||
|
dimensions: DimensionTag? = null,
|
||||||
|
) = arrayOfNotNull(TAG_NAME, url, dimensions?.toString())
|
||||||
|
|
||||||
|
fun assemble(image: ImageTag) = assemble(image.url, image.dimensions)
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.definition.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class NameTag {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "name"
|
||||||
|
|
||||||
|
fun parse(tag: Array<String>): String? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(name: String) = arrayOf(TAG_NAME, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.definition.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
|
||||||
|
import com.vitorpamplona.quartz.utils.arrayOfNotNull
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class ThumbTag(
|
||||||
|
val url: String,
|
||||||
|
val dimensions: DimensionTag? = null,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "thumb"
|
||||||
|
|
||||||
|
fun parse(tag: Array<String>): ThumbTag? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
val dims = tag.getOrNull(2)?.let { DimensionTag.parse(it) }
|
||||||
|
return ThumbTag(tag[1], dims)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseUrl(tag: Array<String>): String? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(
|
||||||
|
url: String,
|
||||||
|
dimensions: DimensionTag? = null,
|
||||||
|
) = arrayOfNotNull(TAG_NAME, url, dimensions?.toString())
|
||||||
|
|
||||||
|
fun assemble(thumb: ThumbTag) = assemble(thumb.url, thumb.dimensions)
|
||||||
|
|
||||||
|
fun assemble(thumbs: List<ThumbTag>) = thumbs.map { assemble(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
-6
@@ -18,20 +18,24 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* 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.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip58Badges
|
package com.vitorpamplona.quartz.nip58Badges.profiles
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
|
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
|
||||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
|
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
|
||||||
import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider
|
import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
|
import com.vitorpamplona.quartz.nip01Core.tags.dTag.dTag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||||
|
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.profiles.tags.AcceptedBadge
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
class BadgeProfilesEvent(
|
class BadgeProfilesEvent(
|
||||||
@@ -57,17 +61,32 @@ class BadgeProfilesEvent(
|
|||||||
|
|
||||||
override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId)
|
override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId)
|
||||||
|
|
||||||
fun badgeAwardEvents() = taggedEvents()
|
fun acceptedBadges() = tags.acceptedBadges()
|
||||||
|
|
||||||
fun badgeAwardDefinitions() = taggedAddresses()
|
fun badgeAwardEvents() = tags.badgeAwardEvents()
|
||||||
|
|
||||||
|
fun badgeAwardDefinitions() = tags.badgeAwardDefinitions()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val KIND = 30008
|
const val KIND = 30008
|
||||||
private const val STANDARD_D_TAG = "profile_badges"
|
private const val STANDARD_D_TAG = "profile_badges"
|
||||||
private const val ALT = "List of accepted badges by the author"
|
const val ALT_DESCRIPTION = "List of accepted badges by the author"
|
||||||
|
|
||||||
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, STANDARD_D_TAG)
|
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, STANDARD_D_TAG)
|
||||||
|
|
||||||
fun createAddressTag(pubKey: HexKey): ATag = ATag(KIND, pubKey, STANDARD_D_TAG, null)
|
fun createAddressTag(pubKey: HexKey): ATag = ATag(KIND, pubKey, STANDARD_D_TAG, null)
|
||||||
|
|
||||||
|
fun build(
|
||||||
|
acceptedBadges: List<AcceptedBadge> = emptyList(),
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<BadgeProfilesEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, "", createdAt) {
|
||||||
|
dTag(STANDARD_D_TAG)
|
||||||
|
alt(ALT_DESCRIPTION)
|
||||||
|
if (acceptedBadges.isNotEmpty()) {
|
||||||
|
acceptedBadges(acceptedBadges)
|
||||||
|
}
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.profiles
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.profiles.tags.AcceptedBadge
|
||||||
|
|
||||||
|
fun TagArrayBuilder<BadgeProfilesEvent>.acceptedBadges(badges: List<AcceptedBadge>) = addAll(AcceptedBadge.assemble(badges))
|
||||||
+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.nip58Badges.profiles
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArray
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedAddresses
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
|
||||||
|
import com.vitorpamplona.quartz.nip58Badges.profiles.tags.AcceptedBadge
|
||||||
|
|
||||||
|
fun TagArray.acceptedBadges() = AcceptedBadge.parseAll(this)
|
||||||
|
|
||||||
|
fun TagArray.badgeAwardEvents() = taggedEvents()
|
||||||
|
|
||||||
|
fun TagArray.badgeAwardDefinitions() = taggedAddresses()
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip58Badges.profiles.tags
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArray
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a paired `a` (badge definition) and `e` (badge award) tag
|
||||||
|
* as specified in NIP-58 Profile Badges.
|
||||||
|
*
|
||||||
|
* Clients SHOULD ignore unpaired `a` or `e` tags.
|
||||||
|
*/
|
||||||
|
@Stable
|
||||||
|
class AcceptedBadge(
|
||||||
|
val badgeDefinition: ATag,
|
||||||
|
val badgeAward: ETag,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Parses ordered consecutive pairs of `a` and `e` tags from a tag array.
|
||||||
|
* Tags must appear as sequential pairs: `a`, `e`, `a`, `e`, ...
|
||||||
|
* Unpaired tags are ignored per the spec.
|
||||||
|
*/
|
||||||
|
fun parseAll(tags: TagArray): List<AcceptedBadge> {
|
||||||
|
val result = mutableListOf<AcceptedBadge>()
|
||||||
|
var i = 0
|
||||||
|
while (i < tags.size - 1) {
|
||||||
|
val aTag = ATag.parse(tags[i])
|
||||||
|
if (aTag != null) {
|
||||||
|
val eTag = ETag.parse(tags[i + 1])
|
||||||
|
if (eTag != null) {
|
||||||
|
result.add(AcceptedBadge(aTag, eTag))
|
||||||
|
i += 2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(badges: List<AcceptedBadge>): List<Array<String>> =
|
||||||
|
badges.flatMap { badge ->
|
||||||
|
listOf(
|
||||||
|
badge.badgeDefinition.toATagArray(),
|
||||||
|
badge.badgeAward.toTagArray(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -139,9 +139,9 @@ import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
|||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeAwardEvent
|
import com.vitorpamplona.quartz.nip58Badges.award.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.definition.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.profiles.BadgeProfilesEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||||
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
|
|||||||
Reference in New Issue
Block a user