- Adds support for Follow packs
- Enables top filter by pack as well.
This commit is contained in:
@@ -70,10 +70,12 @@ import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
import com.vitorpamplona.quartz.nip46RemoteSigner.NostrConnectEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
@@ -197,6 +199,7 @@ class EventFactory {
|
||||
FileStorageEvent.KIND -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
FileStorageHeaderEvent.KIND -> FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
FhirResourceEvent.KIND -> FhirResourceEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
FollowListEvent.KIND -> FollowListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GenericRepostEvent.KIND -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GiftWrapEvent.KIND -> GiftWrapEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GitIssueEvent.KIND -> GitIssueEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
@@ -220,9 +223,7 @@ class EventFactory {
|
||||
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
com.vitorpamplona.quartz.nip46RemoteSigner.NostrConnectEvent.KIND ->
|
||||
com.vitorpamplona.quartz.nip46RemoteSigner
|
||||
.NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NostrConnectEvent.KIND -> NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NIP90StatusEvent.KIND -> NIP90StatusEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NIP90ContentDiscoveryRequestEvent.KIND -> NIP90ContentDiscoveryRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NIP90ContentDiscoveryResponseEvent.KIND -> NIP90ContentDiscoveryResponseEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Copyright (c) 2024 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.nip51Lists
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip31Alts.AltTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag.Companion.parse
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Immutable
|
||||
class FollowListEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
fun pubKeys() = tags.mapNotNull(PTag::parseKey)
|
||||
|
||||
fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint)
|
||||
|
||||
fun name() = tags.firstNotNullOfOrNull(NameTag::parse)
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||
|
||||
fun nameOrTitle() = name() ?: title()
|
||||
|
||||
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||
|
||||
companion object {
|
||||
const val KIND = 39089
|
||||
const val ALT = "List of people to follow"
|
||||
|
||||
fun createListWithUser(
|
||||
name: String,
|
||||
pubKeyHex: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
content = "",
|
||||
tags = arrayOf(arrayOf("d", name), arrayOf("p", pubKeyHex)),
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
|
||||
fun addUsers(
|
||||
earlierVersion: FollowListEvent,
|
||||
listPubKeyHex: List<String>,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
content = earlierVersion.content,
|
||||
tags =
|
||||
earlierVersion.tags.plus(
|
||||
listPubKeyHex.map { arrayOf("p", it) },
|
||||
),
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
|
||||
fun addUser(
|
||||
earlierVersion: FollowListEvent,
|
||||
pubKeyHex: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) = addUsers(earlierVersion, listOf(pubKeyHex), signer, createdAt, onReady)
|
||||
|
||||
fun removeUser(
|
||||
earlierVersion: FollowListEvent,
|
||||
pubKeyHex: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
content = earlierVersion.content,
|
||||
tags =
|
||||
earlierVersion.tags
|
||||
.filter { it.size > 1 && !(it[0] == "p" && it[1] == pubKeyHex) }
|
||||
.toTypedArray(),
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
|
||||
fun create(
|
||||
content: String,
|
||||
tags: Array<Array<String>>,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
val newTags =
|
||||
if (tags.any { it.size > 1 && it[0] == "alt" }) {
|
||||
tags
|
||||
} else {
|
||||
tags + AltTag.assemble(ALT)
|
||||
}
|
||||
|
||||
signer.sign(createdAt, KIND, newTags, content, onReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,8 @@ import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohashes
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.HashtagTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
@@ -63,6 +65,10 @@ abstract class GeneralListEvent(
|
||||
@Deprecated("NIP-51 has deprecated Title. Use name instead", ReplaceWith("name()"))
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||
|
||||
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||
|
||||
fun nameOrTitle() = name() ?: title()
|
||||
|
||||
fun filterTagList(
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2024 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.nip51Lists.tags
|
||||
|
||||
class DescriptionTag {
|
||||
companion object {
|
||||
const val TAG_NAME = "description"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(tag: Array<String>): String? {
|
||||
if (tag.size < 2 || tag[0] != TAG_NAME || tag[1].isEmpty()) return null
|
||||
return tag[1]
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun assemble(name: String) = arrayOf(TAG_NAME, name)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2024 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.nip51Lists.tags
|
||||
|
||||
class ImageTag {
|
||||
companion object {
|
||||
const val TAG_NAME = "image"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(tag: Array<String>): String? {
|
||||
if (tag.size < 2 || tag[0] != TAG_NAME || tag[1].isEmpty()) return null
|
||||
return tag[1]
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun assemble(name: String) = arrayOf(TAG_NAME, name)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user