Removes old follows in Contact lists.

This commit is contained in:
Vitor Pamplona
2025-07-08 19:16:28 -04:00
parent c5ed0cfa60
commit 2ee1285ea1
9 changed files with 67 additions and 193 deletions
@@ -30,16 +30,11 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNote
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseAsHint
import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHash
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.countHashtags
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHash
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseKey
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
import com.vitorpamplona.quartz.nip02FollowList.tags.AddressFollowTag
import com.vitorpamplona.quartz.nip02FollowList.tags.ContactTag
import com.vitorpamplona.quartz.nip31Alts.AltTag
import com.vitorpamplona.quartz.utils.TimeUtils
@@ -71,18 +66,16 @@ class ContactListEvent(
/**
* Returns a list of a-tags that are verified as correct.
*/
fun verifiedFollowAddressSet(): Set<HexKey> = tags.mapNotNullTo(HashSet(), AddressFollowTag::parseValidAddress)
@Deprecated("Use CommunityListEvent instead.")
fun verifiedFollowAddressSet(): Set<HexKey> = tags.mapNotNullTo(HashSet(), ATag::parseValidAddress)
fun unverifiedFollowKeySet() = tags.mapNotNull(ContactTag::parseKey)
@Deprecated("Use HashtagListEvent instead.")
fun unverifiedFollowTagSet() = tags.hashtags()
fun countFollowTags() = tags.countHashtags()
fun follows() = tags.mapNotNull(ContactTag::parseValid)
fun followsTags() = hashtags()
fun relays(): Map<NormalizedRelayUrl, ReadWrite>? {
val regular = RelaySet.parse(content)
@@ -106,9 +99,6 @@ class ContactListEvent(
fun createFromScratch(
followUsers: List<ContactTag> = emptyList(),
followTags: List<String> = emptyList(),
followGeohashes: List<String> = emptyList(),
followCommunities: List<ATag> = emptyList(),
relayUse: Map<String, ReadWrite>? = emptyMap(),
signer: NostrSignerSync,
createdAt: Long = TimeUtils.now(),
@@ -117,19 +107,13 @@ class ContactListEvent(
val tags =
listOf(AltTag.assemble(ALT)) +
followUsers.map { it.toTagArray() } +
followTags.map { arrayOf("t", it) } +
followCommunities.map { it.toATagArray() } +
followGeohashes.map { arrayOf("g", it) }
followUsers.map { it.toTagArray() }
return signer.sign(createdAt, KIND, tags.toTypedArray(), content)
}
fun createFromScratch(
followUsers: List<ContactTag>,
followTags: List<String>,
followGeohashes: List<String>,
followCommunities: List<ATag>,
relayUse: Map<String, ReadWrite>?,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
@@ -137,12 +121,7 @@ class ContactListEvent(
) {
val content = relayUse?.let { RelaySet.assemble(it) } ?: ""
val tags =
followUsers.map { it.toTagArray() } +
followTags.map { arrayOf("t", it) } +
followCommunities.map { it.toATagArray() } +
followGeohashes.map { arrayOf("g", it) }
val tags = followUsers.map { it.toTagArray() }
return create(
content = content,
tags = tags.toTypedArray(),
@@ -188,118 +167,6 @@ class ContactListEvent(
)
}
fun followHashtag(
earlierVersion: ContactListEvent,
hashtag: String,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit,
) {
if (earlierVersion.isTaggedHash(hashtag)) return
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = arrayOf("t", hashtag)),
signer = signer,
createdAt = createdAt,
onReady = onReady,
)
}
fun unfollowHashtag(
earlierVersion: ContactListEvent,
hashtag: String,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit,
) {
if (!earlierVersion.isTaggedHash(hashtag)) return
return create(
content = earlierVersion.content,
tags =
earlierVersion.tags.filter { it.size > 1 && !it[1].equals(hashtag, true) }.toTypedArray(),
signer = signer,
createdAt = createdAt,
onReady = onReady,
)
}
fun followGeohash(
earlierVersion: ContactListEvent,
hashtag: String,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit,
) {
if (earlierVersion.isTaggedGeoHash(hashtag)) return
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = arrayOf("g", hashtag)),
signer = signer,
createdAt = createdAt,
onReady = onReady,
)
}
fun unfollowGeohash(
earlierVersion: ContactListEvent,
hashtag: String,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit,
) {
if (!earlierVersion.isTaggedGeoHash(hashtag)) return
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != hashtag }.toTypedArray(),
signer = signer,
createdAt = createdAt,
onReady = onReady,
)
}
fun followAddressableEvent(
earlierVersion: ContactListEvent,
aTag: ATag,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit,
) {
if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return
return create(
content = earlierVersion.content,
tags =
earlierVersion.tags.plus(
element = aTag.toATagArray(),
),
signer = signer,
createdAt = createdAt,
onReady = onReady,
)
}
fun unfollowAddressableEvent(
earlierVersion: ContactListEvent,
aTag: ATag,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit,
) {
if (!earlierVersion.isTaggedAddressableNote(aTag.toTag())) return
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() }.toTypedArray(),
signer = signer,
createdAt = createdAt,
onReady = onReady,
)
}
fun updateRelayList(
earlierVersion: ContactListEvent,
relayUse: Map<String, ReadWrite>?,
@@ -1,25 +0,0 @@
/**
* 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.nip02FollowList.tags
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
typealias AddressFollowTag = ATag