Merge pull request #2017 from vitorpamplona/claude/implement-nip5a-rendering-5ioVq
feat: implement NIP-5A static website event rendering
This commit is contained in:
@@ -173,6 +173,8 @@ import com.vitorpamplona.quartz.nip58Badges.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
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip62RequestToVanish.RequestToVanishEvent
|
import com.vitorpamplona.quartz.nip62RequestToVanish.RequestToVanishEvent
|
||||||
import com.vitorpamplona.quartz.nip64Chess.challenge.accept.LiveChessGameAcceptEvent
|
import com.vitorpamplona.quartz.nip64Chess.challenge.accept.LiveChessGameAcceptEvent
|
||||||
import com.vitorpamplona.quartz.nip64Chess.challenge.offer.LiveChessGameChallengeEvent
|
import com.vitorpamplona.quartz.nip64Chess.challenge.offer.LiveChessGameChallengeEvent
|
||||||
@@ -1171,6 +1173,18 @@ object LocalCache : ILocalCache, ICacheProvider {
|
|||||||
wasVerified: Boolean,
|
wasVerified: Boolean,
|
||||||
) = consumeBaseReplaceable(event, relay, wasVerified)
|
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||||
|
|
||||||
|
fun consume(
|
||||||
|
event: RootSiteEvent,
|
||||||
|
relay: NormalizedRelayUrl?,
|
||||||
|
wasVerified: Boolean,
|
||||||
|
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||||
|
|
||||||
|
fun consume(
|
||||||
|
event: NamedSiteEvent,
|
||||||
|
relay: NormalizedRelayUrl?,
|
||||||
|
wasVerified: Boolean,
|
||||||
|
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||||
|
|
||||||
fun consume(
|
fun consume(
|
||||||
event: ChannelListEvent,
|
event: ChannelListEvent,
|
||||||
relay: NormalizedRelayUrl?,
|
relay: NormalizedRelayUrl?,
|
||||||
@@ -3178,6 +3192,8 @@ object LocalCache : ILocalCache, ICacheProvider {
|
|||||||
is GitReplyEvent -> consume(event, relay, wasVerified)
|
is GitReplyEvent -> consume(event, relay, wasVerified)
|
||||||
is GitPatchEvent -> consume(event, relay, wasVerified)
|
is GitPatchEvent -> consume(event, relay, wasVerified)
|
||||||
is GitRepositoryEvent -> consume(event, relay, wasVerified)
|
is GitRepositoryEvent -> consume(event, relay, wasVerified)
|
||||||
|
is RootSiteEvent -> consume(event, relay, wasVerified)
|
||||||
|
is NamedSiteEvent -> consume(event, relay, wasVerified)
|
||||||
is ChessGameEvent -> consume(event, relay, wasVerified)
|
is ChessGameEvent -> consume(event, relay, wasVerified)
|
||||||
is RelayFeedsListEvent -> consume(event, relay, wasVerified)
|
is RelayFeedsListEvent -> consume(event, relay, wasVerified)
|
||||||
is JesterEvent -> consume(event, relay, wasVerified)
|
is JesterEvent -> consume(event, relay, wasVerified)
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderLongFormContent
|
|||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderMintRecommendation
|
import com.vitorpamplona.amethyst.ui.note.types.RenderMintRecommendation
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90ContentDiscoveryResponse
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90ContentDiscoveryResponse
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90Status
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90Status
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNamedSiteEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderNipContent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNipContent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPinListEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPinListEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPoll
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPoll
|
||||||
@@ -154,6 +155,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderRelayLeaveRequest
|
|||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayMembershipList
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayMembershipList
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayRemoveMember
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayRemoveMember
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderReport
|
import com.vitorpamplona.amethyst.ui.note.types.RenderReport
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRootSiteEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderTextEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderTextEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderTextModificationEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderTextModificationEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderThread
|
import com.vitorpamplona.amethyst.ui.note.types.RenderThread
|
||||||
@@ -255,6 +257,8 @@ 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.BadgeAwardEvent
|
||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip64Chess.challenge.offer.LiveChessGameChallengeEvent
|
import com.vitorpamplona.quartz.nip64Chess.challenge.offer.LiveChessGameChallengeEvent
|
||||||
import com.vitorpamplona.quartz.nip64Chess.end.LiveChessGameEndEvent
|
import com.vitorpamplona.quartz.nip64Chess.end.LiveChessGameEndEvent
|
||||||
import com.vitorpamplona.quartz.nip64Chess.game.ChessGameEvent
|
import com.vitorpamplona.quartz.nip64Chess.game.ChessGameEvent
|
||||||
@@ -985,6 +989,14 @@ private fun RenderNoteRow(
|
|||||||
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is RootSiteEvent -> {
|
||||||
|
RenderRootSiteEvent(baseNote, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
|
||||||
|
is NamedSiteEvent -> {
|
||||||
|
RenderNamedSiteEvent(baseNote, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
|
||||||
is GitPatchEvent -> {
|
is GitPatchEvent -> {
|
||||||
RenderGitPatchEvent(
|
RenderGitPatchEvent(
|
||||||
baseNote,
|
baseNote,
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.note.types
|
||||||
|
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RenderRootSiteEvent(
|
||||||
|
baseNote: Note,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val event = baseNote.event as? RootSiteEvent ?: return
|
||||||
|
|
||||||
|
RenderStaticWebsite(
|
||||||
|
title = event.title(),
|
||||||
|
description = event.description(),
|
||||||
|
source = event.source(),
|
||||||
|
servers = event.servers(),
|
||||||
|
identifier = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RenderNamedSiteEvent(
|
||||||
|
baseNote: Note,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val event = baseNote.event as? NamedSiteEvent ?: return
|
||||||
|
|
||||||
|
RenderStaticWebsite(
|
||||||
|
title = event.title(),
|
||||||
|
description = event.description(),
|
||||||
|
source = event.source(),
|
||||||
|
servers = event.servers(),
|
||||||
|
identifier = event.identifier(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderStaticWebsite(
|
||||||
|
title: String?,
|
||||||
|
description: String?,
|
||||||
|
source: String?,
|
||||||
|
servers: List<String>,
|
||||||
|
identifier: String?,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.clip(shape = QuoteBorder)
|
||||||
|
.border(
|
||||||
|
1.dp,
|
||||||
|
MaterialTheme.colorScheme.subtleBorder,
|
||||||
|
QuoteBorder,
|
||||||
|
).padding(Size10dp),
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
val displayTitle =
|
||||||
|
title
|
||||||
|
?: identifier
|
||||||
|
?: stringRes(id = R.string.nsite_root_site)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringRes(id = R.string.nsite_title, displayTitle),
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
|
description?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(vertical = Size5dp),
|
||||||
|
maxLines = 3,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(thickness = DividerThickness)
|
||||||
|
|
||||||
|
source?.let {
|
||||||
|
Row(Modifier.fillMaxWidth().padding(top = Size5dp)) {
|
||||||
|
Text(
|
||||||
|
text = stringRes(id = R.string.nsite_source),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
ClickableUrl(
|
||||||
|
url = it,
|
||||||
|
urlText = it.removePrefix("https://").removePrefix("http://"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servers.isNotEmpty()) {
|
||||||
|
Row(Modifier.fillMaxWidth().padding(top = Size5dp)) {
|
||||||
|
Text(
|
||||||
|
text = stringRes(id = R.string.nsite_servers),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
Column {
|
||||||
|
servers.forEach { server ->
|
||||||
|
ClickableUrl(
|
||||||
|
url = server,
|
||||||
|
urlText = server.removePrefix("https://").removePrefix("http://"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -162,6 +162,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderHighlight
|
|||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderInteractiveStory
|
import com.vitorpamplona.amethyst.ui.note.types.RenderInteractiveStory
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderLiveActivityChatMessage
|
import com.vitorpamplona.amethyst.ui.note.types.RenderLiveActivityChatMessage
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderLnZap
|
import com.vitorpamplona.amethyst.ui.note.types.RenderLnZap
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNamedSiteEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderMintRecommendation
|
import com.vitorpamplona.amethyst.ui.note.types.RenderMintRecommendation
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPinListEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPinListEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPoll
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPoll
|
||||||
@@ -174,6 +175,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderRelayJoinRequest
|
|||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayLeaveRequest
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayLeaveRequest
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayMembershipList
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayMembershipList
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayRemoveMember
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRelayRemoveMember
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.types.RenderRootSiteEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderTextEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderTextEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderTextModificationEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderTextModificationEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderTorrent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderTorrent
|
||||||
@@ -262,6 +264,8 @@ 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.BadgeDefinitionEvent
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.NamedSiteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.RootSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||||
import com.vitorpamplona.quartz.nip66RelayMonitor.discovery.RelayDiscoveryEvent
|
import com.vitorpamplona.quartz.nip66RelayMonitor.discovery.RelayDiscoveryEvent
|
||||||
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
import com.vitorpamplona.quartz.nip68Picture.PictureEvent
|
||||||
@@ -686,6 +690,10 @@ private fun FullBleedNoteCompose(
|
|||||||
RenderFhirResource(baseNote, accountViewModel, nav)
|
RenderFhirResource(baseNote, accountViewModel, nav)
|
||||||
} else if (noteEvent is GitRepositoryEvent) {
|
} else if (noteEvent is GitRepositoryEvent) {
|
||||||
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||||
|
} else if (noteEvent is RootSiteEvent) {
|
||||||
|
RenderRootSiteEvent(baseNote, accountViewModel, nav)
|
||||||
|
} else if (noteEvent is NamedSiteEvent) {
|
||||||
|
RenderNamedSiteEvent(baseNote, accountViewModel, nav)
|
||||||
} else if (noteEvent is InteractiveStoryBaseEvent) {
|
} else if (noteEvent is InteractiveStoryBaseEvent) {
|
||||||
RenderInteractiveStory(
|
RenderInteractiveStory(
|
||||||
baseNote,
|
baseNote,
|
||||||
|
|||||||
@@ -1488,6 +1488,10 @@
|
|||||||
<string name="git_repository">Git Repository: %1$s</string>
|
<string name="git_repository">Git Repository: %1$s</string>
|
||||||
<string name="git_web_address">Web:</string>
|
<string name="git_web_address">Web:</string>
|
||||||
<string name="git_clone_address">Clone:</string>
|
<string name="git_clone_address">Clone:</string>
|
||||||
|
<string name="nsite_title">Static Website: %1$s</string>
|
||||||
|
<string name="nsite_root_site">Root Site</string>
|
||||||
|
<string name="nsite_source">Source:</string>
|
||||||
|
<string name="nsite_servers">Servers:</string>
|
||||||
<string name="existed_since">OTS: %1$s</string>
|
<string name="existed_since">OTS: %1$s</string>
|
||||||
|
|
||||||
<string name="ots_info_title">Timestamp Proof</string>
|
<string name="ots_info_title">Timestamp Proof</string>
|
||||||
|
|||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip5aStaticWebsites
|
||||||
|
|
||||||
|
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.nip5aStaticWebsites.tags.PathTag
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class NamedSiteEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: Array<Array<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey,
|
||||||
|
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||||
|
fun paths() = tags.sitePaths()
|
||||||
|
|
||||||
|
fun servers() = tags.siteServers()
|
||||||
|
|
||||||
|
fun title() = tags.siteTitle()
|
||||||
|
|
||||||
|
fun description() = tags.siteDescription()
|
||||||
|
|
||||||
|
fun source() = tags.siteSource()
|
||||||
|
|
||||||
|
fun identifier() = dTag()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KIND = 35128
|
||||||
|
const val ALT_DESCRIPTION = "Named Static Website"
|
||||||
|
|
||||||
|
fun build(
|
||||||
|
identifier: String,
|
||||||
|
paths: List<PathTag>,
|
||||||
|
servers: List<String> = emptyList(),
|
||||||
|
title: String? = null,
|
||||||
|
description: String? = null,
|
||||||
|
source: String? = null,
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<NamedSiteEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, "", createdAt) {
|
||||||
|
alt(ALT_DESCRIPTION)
|
||||||
|
dTag(identifier)
|
||||||
|
sitePaths(paths)
|
||||||
|
if (servers.isNotEmpty()) siteServers(servers)
|
||||||
|
title?.let { siteTitle(it) }
|
||||||
|
description?.let { siteDescription(it) }
|
||||||
|
source?.let { siteSource(it) }
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip5aStaticWebsites
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.BaseReplaceableEvent
|
||||||
|
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.nip31Alts.alt
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.PathTag
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class RootSiteEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: Array<Array<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey,
|
||||||
|
) : BaseReplaceableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||||
|
fun paths() = tags.sitePaths()
|
||||||
|
|
||||||
|
fun servers() = tags.siteServers()
|
||||||
|
|
||||||
|
fun title() = tags.siteTitle()
|
||||||
|
|
||||||
|
fun description() = tags.siteDescription()
|
||||||
|
|
||||||
|
fun source() = tags.siteSource()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KIND = 15128
|
||||||
|
const val ALT_DESCRIPTION = "Static Website"
|
||||||
|
|
||||||
|
fun build(
|
||||||
|
paths: List<PathTag>,
|
||||||
|
servers: List<String> = emptyList(),
|
||||||
|
title: String? = null,
|
||||||
|
description: String? = null,
|
||||||
|
source: String? = null,
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<RootSiteEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, "", createdAt) {
|
||||||
|
alt(ALT_DESCRIPTION)
|
||||||
|
sitePaths(paths)
|
||||||
|
if (servers.isNotEmpty()) siteServers(servers)
|
||||||
|
title?.let { siteTitle(it) }
|
||||||
|
description?.let { siteDescription(it) }
|
||||||
|
source?.let { siteSource(it) }
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+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.nip5aStaticWebsites
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.DescriptionTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.PathTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.ServerTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.SourceTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.TitleTag
|
||||||
|
|
||||||
|
fun <T : Event> TagArrayBuilder<T>.sitePaths(paths: List<PathTag>) = addAll(PathTag.assemble(paths))
|
||||||
|
|
||||||
|
fun <T : Event> TagArrayBuilder<T>.siteServers(servers: List<String>) = addAll(ServerTag.assemble(servers))
|
||||||
|
|
||||||
|
fun <T : Event> TagArrayBuilder<T>.siteTitle(title: String) = addUnique(TitleTag.assemble(title))
|
||||||
|
|
||||||
|
fun <T : Event> TagArrayBuilder<T>.siteDescription(description: String) = addUnique(DescriptionTag.assemble(description))
|
||||||
|
|
||||||
|
fun <T : Event> TagArrayBuilder<T>.siteSource(url: String) = addUnique(SourceTag.assemble(url))
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip5aStaticWebsites
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArray
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.DescriptionTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.PathTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.ServerTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.SourceTag
|
||||||
|
import com.vitorpamplona.quartz.nip5aStaticWebsites.tags.TitleTag
|
||||||
|
|
||||||
|
fun TagArray.sitePaths() = mapNotNull(PathTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.siteServers() = mapNotNull(ServerTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.siteTitle() = firstNotNullOfOrNull(TitleTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.siteDescription() = firstNotNullOfOrNull(DescriptionTag::parse)
|
||||||
|
|
||||||
|
fun TagArray.siteSource() = firstNotNullOfOrNull(SourceTag::parse)
|
||||||
+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.nip5aStaticWebsites.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class DescriptionTag {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "description"
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip5aStaticWebsites.tags
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
class PathTag(
|
||||||
|
val path: String,
|
||||||
|
val hash: String,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "path"
|
||||||
|
|
||||||
|
fun parse(tag: Array<String>): PathTag? {
|
||||||
|
ensure(tag.has(2)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
ensure(tag[2].isNotEmpty()) { return null }
|
||||||
|
return PathTag(tag[1], tag[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(
|
||||||
|
path: String,
|
||||||
|
hash: String,
|
||||||
|
) = arrayOf(TAG_NAME, path, hash)
|
||||||
|
|
||||||
|
fun assemble(pathTag: PathTag) = assemble(pathTag.path, pathTag.hash)
|
||||||
|
|
||||||
|
fun assemble(paths: List<PathTag>) = paths.map { assemble(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.nip5aStaticWebsites.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class ServerTag {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "server"
|
||||||
|
|
||||||
|
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(url: String) = arrayOf(TAG_NAME, url)
|
||||||
|
|
||||||
|
fun assemble(urls: List<String>) = urls.map { assemble(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+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.nip5aStaticWebsites.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class SourceTag {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "source"
|
||||||
|
|
||||||
|
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(url: String) = arrayOf(TAG_NAME, url)
|
||||||
|
}
|
||||||
|
}
|
||||||
+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.nip5aStaticWebsites.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class TitleTag {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "title"
|
||||||
|
|
||||||
|
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(title: String) = arrayOf(TAG_NAME, title)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -125,6 +125,8 @@ import com.vitorpamplona.quartz.nip58Badges.BadgeDefinitionEvent
|
|||||||
import com.vitorpamplona.quartz.nip58Badges.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.nip58Badges.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.RootSiteEvent
|
||||||
import com.vitorpamplona.quartz.nip60Cashu.history.CashuSpendingHistoryEvent
|
import com.vitorpamplona.quartz.nip60Cashu.history.CashuSpendingHistoryEvent
|
||||||
import com.vitorpamplona.quartz.nip60Cashu.quote.CashuMintQuoteEvent
|
import com.vitorpamplona.quartz.nip60Cashu.quote.CashuMintQuoteEvent
|
||||||
import com.vitorpamplona.quartz.nip60Cashu.token.CashuTokenEvent
|
import com.vitorpamplona.quartz.nip60Cashu.token.CashuTokenEvent
|
||||||
@@ -310,6 +312,7 @@ class EventFactory {
|
|||||||
MintRecommendationEvent.KIND -> MintRecommendationEvent(id, pubKey, createdAt, tags, content, sig)
|
MintRecommendationEvent.KIND -> MintRecommendationEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
NamedSiteEvent.KIND -> NamedSiteEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NipTextEvent.KIND -> NipTextEvent(id, pubKey, createdAt, tags, content, sig)
|
NipTextEvent.KIND -> NipTextEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NutzapEvent.KIND -> NutzapEvent(id, pubKey, createdAt, tags, content, sig)
|
NutzapEvent.KIND -> NutzapEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
@@ -349,6 +352,7 @@ class EventFactory {
|
|||||||
RelayMonitorEvent.KIND -> RelayMonitorEvent(id, pubKey, createdAt, tags, content, sig)
|
RelayMonitorEvent.KIND -> RelayMonitorEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
RelaySetEvent.KIND -> RelaySetEvent(id, pubKey, createdAt, tags, content, sig)
|
RelaySetEvent.KIND -> RelaySetEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
ReportEvent.KIND -> ReportEvent(id, pubKey, createdAt, tags, content, sig)
|
ReportEvent.KIND -> ReportEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
RootSiteEvent.KIND -> RootSiteEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
RepostEvent.KIND -> RepostEvent(id, pubKey, createdAt, tags, content, sig)
|
RepostEvent.KIND -> RepostEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
RequestToVanishEvent.KIND -> RequestToVanishEvent(id, pubKey, createdAt, tags, content, sig)
|
RequestToVanishEvent.KIND -> RequestToVanishEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
SealedRumorEvent.KIND -> SealedRumorEvent(id, pubKey, createdAt, tags, content, sig)
|
SealedRumorEvent.KIND -> SealedRumorEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
|||||||
Reference in New Issue
Block a user