created loggedInWithAmber in accountViewModel, changed some events to use keypair

This commit is contained in:
greenart7c3
2023-08-23 15:56:31 -03:00
parent 632400f52c
commit b10e875941
9 changed files with 143 additions and 258 deletions

View File

@@ -169,8 +169,7 @@ class Account(
val event = ContactListEvent.updateRelayList(
earlierVersion = contactList,
relayUse = relays,
pubKey = keyPair.pubKey.toHexKey(),
privateKey = keyPair.privKey
keyPair = keyPair
)
if (!signEvent) {
@@ -188,8 +187,7 @@ class Account(
followCommunities = listOf(),
followEvents = DefaultChannels.toList(),
relayUse = relays,
privateKey = keyPair.privKey!!,
publicKey = if (!signEvent) keyPair.pubKey else null
keyPair = keyPair
)
if (!signEvent) {
@@ -511,11 +509,7 @@ class Account(
if (followingCommunities.isNotEmpty()) {
followingCommunities.forEach {
ATag.parse(it, null)?.let {
returningContactList = if (keyPair.privKey == null) {
ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.pubKey.toHexKey())
} else {
ContactListEvent.followAddressableEvent(returningContactList, it, keyPair.pubKey.toHexKey(), keyPair.privKey)
}
returningContactList = ContactListEvent.followAddressableEvent(returningContactList, it, keyPair)
}
}
followingCommunities = emptySet()
@@ -523,11 +517,7 @@ class Account(
if (followingChannels.isNotEmpty()) {
followingChannels.forEach {
returningContactList = if (keyPair.privKey == null) {
ContactListEvent.followEvent(returningContactList, it, keyPair.pubKey.toHexKey())
} else {
ContactListEvent.followEvent(returningContactList, it, keyPair.pubKey.toHexKey(), keyPair.privKey)
}
returningContactList = ContactListEvent.followEvent(returningContactList, it, keyPair)
}
followingChannels = emptySet()
}
@@ -541,11 +531,7 @@ class Account(
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
val event = if (contactList != null) {
if (signEvent) {
ContactListEvent.followUser(contactList, user.pubkeyHex, keyPair.privKey!!)
} else {
ContactListEvent.followUser(contactList, user.pubkeyHex, keyPair.pubKey.toHexKey())
}
ContactListEvent.followUser(contactList, user.pubkeyHex, keyPair)
} else {
ContactListEvent.createFromScratch(
followUsers = listOf(Contact(user.pubkeyHex, null)),
@@ -554,8 +540,7 @@ class Account(
followCommunities = emptyList(),
followEvents = DefaultChannels.toList(),
relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
privateKey = keyPair.privKey,
publicKey = if (signEvent) null else keyPair.pubKey
keyPair = keyPair
)
}
@@ -574,7 +559,7 @@ class Account(
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
val event = if (contactList != null) {
ContactListEvent.followEvent(contactList, channel.idHex, keyPair.pubKey.toHexKey(), keyPair.privKey)
ContactListEvent.followEvent(contactList, channel.idHex, keyPair)
} else {
ContactListEvent.createFromScratch(
followUsers = emptyList(),
@@ -583,8 +568,7 @@ class Account(
followCommunities = emptyList(),
followEvents = DefaultChannels.toList().plus(channel.idHex),
relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
publicKey = if (!signEvent) keyPair.pubKey else null,
privateKey = keyPair.privKey
keyPair = keyPair
)
}
@@ -603,7 +587,7 @@ class Account(
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
val event = if (contactList != null) {
ContactListEvent.followAddressableEvent(contactList, community.address, keyPair.pubKey.toHexKey(), keyPair.privKey)
ContactListEvent.followAddressableEvent(contactList, community.address, keyPair)
} else {
val relays = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) }
ContactListEvent.createFromScratch(
@@ -613,8 +597,7 @@ class Account(
followCommunities = listOf(community.address),
followEvents = DefaultChannels.toList(),
relayUse = relays,
publicKey = if (!signEvent) keyPair.pubKey else null,
privateKey = keyPair.privKey
keyPair = keyPair
)
}
@@ -633,19 +616,11 @@ class Account(
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
val event = if (contactList != null) {
if (signEvent) {
ContactListEvent.followHashtag(
contactList,
tag,
keyPair.privKey!!
)
} else {
ContactListEvent.followHashtag(
contactList,
tag,
keyPair.pubKey.toHexKey()
)
}
ContactListEvent.followHashtag(
contactList,
tag,
keyPair
)
} else {
ContactListEvent.createFromScratch(
followUsers = emptyList(),
@@ -654,8 +629,7 @@ class Account(
followCommunities = emptyList(),
followEvents = DefaultChannels.toList(),
relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
privateKey = keyPair.privKey,
publicKey = if (signEvent) null else keyPair.pubKey
keyPair = keyPair
)
}
@@ -668,8 +642,8 @@ class Account(
return null
}
fun followGeohash(geohash: String) {
if (!isWriteable()) return
fun followGeohash(geohash: String, signEvent: Boolean): ContactListEvent? {
if (!isWriteable() && signEvent) return null
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
@@ -677,7 +651,7 @@ class Account(
ContactListEvent.followGeohash(
contactList,
geohash,
keyPair.privKey!!
keyPair
)
} else {
ContactListEvent.createFromScratch(
@@ -687,12 +661,17 @@ class Account(
followCommunities = emptyList(),
followEvents = DefaultChannels.toList(),
relayUse = Constants.defaultRelays.associate { it.url to ContactListEvent.ReadWrite(it.read, it.write) },
privateKey = keyPair.privKey!!
keyPair = keyPair
)
}
if (!signEvent) {
return event
}
Client.send(event)
LocalCache.consume(event)
return null
}
fun unfollow(user: User, signEvent: Boolean = true): ContactListEvent? {
@@ -701,20 +680,16 @@ class Account(
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
if (contactList != null && contactList.tags.isNotEmpty()) {
if (!signEvent) {
return ContactListEvent.unfollowUser(
contactList,
user.pubkeyHex,
keyPair.pubKey.toHexKey()
)
}
val event = ContactListEvent.unfollowUser(
contactList,
user.pubkeyHex,
keyPair.privKey!!
keyPair
)
if (!signEvent) {
return event
}
Client.send(event)
LocalCache.consume(event)
}
@@ -728,20 +703,16 @@ class Account(
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
if (contactList != null && contactList.tags.isNotEmpty()) {
if (!signEvent) {
return ContactListEvent.unfollowHashtag(
contactList,
tag,
keyPair.pubKey.toHexKey()
)
}
val event = ContactListEvent.unfollowHashtag(
contactList,
tag,
keyPair.privKey!!
keyPair
)
if (!signEvent) {
return event
}
Client.send(event)
LocalCache.consume(event)
@@ -751,8 +722,8 @@ class Account(
return null
}
fun unfollowGeohash(geohash: String) {
if (!isWriteable()) return
fun unfollowGeohash(geohash: String, signEvent: Boolean): ContactListEvent? {
if (!isWriteable() && signEvent) return null
val contactList = migrateCommunitiesAndChannelsIfNeeded(userProfile().latestContactList)
@@ -760,12 +731,18 @@ class Account(
val event = ContactListEvent.unfollowGeohash(
contactList,
geohash,
keyPair.privKey!!
keyPair
)
if (!signEvent) {
return event
}
Client.send(event)
LocalCache.consume(event)
return null
}
return null
}
fun unfollow(channel: Channel, signEvent: Boolean): ContactListEvent? {
@@ -777,8 +754,7 @@ class Account(
val event = ContactListEvent.unfollowEvent(
contactList,
channel.idHex,
keyPair.pubKey.toHexKey(),
keyPair.privKey
keyPair
)
if (!signEvent) {
@@ -800,8 +776,7 @@ class Account(
val event = ContactListEvent.unfollowAddressableEvent(
contactList,
community.address,
keyPair.pubKey.toHexKey(),
keyPair.privKey
keyPair
)
if (!signEvent) {

View File

@@ -59,7 +59,6 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.RelayInformation
import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.service.PackageUtils
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.service.relays.Constants.defaultRelays
import com.vitorpamplona.amethyst.service.relays.FeedType
@@ -145,7 +144,7 @@ fun NewRelayListView(onClose: () -> Unit, accountViewModel: AccountViewModel, re
PostButton(
onPost = {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = postViewModel.create(false)
} else {
postViewModel.create(true)

View File

@@ -29,7 +29,6 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.PackageUtils
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
import com.vitorpamplona.amethyst.ui.screen.ZapReqResponse
@@ -233,7 +232,7 @@ fun ShowFollowingOrUnfollowingButton(
if (isFollowing) {
UnfollowButton {
if (!accountViewModel.isWriteable()) {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.unfollow(baseAuthor, false)
} else {
scope.launch {
@@ -255,7 +254,7 @@ fun ShowFollowingOrUnfollowingButton(
} else {
FollowButton {
if (!accountViewModel.isWriteable()) {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.follow(baseAuthor, false)
} else {
scope.launch {

View File

@@ -84,6 +84,10 @@ class AccountViewModel(val account: Account) : ViewModel() {
return account.isWriteable()
}
fun loggedInWithAmber(): Boolean {
return account.loginWithAmber
}
fun userProfile(): User {
return account.userProfile()
}

View File

@@ -86,7 +86,6 @@ import com.vitorpamplona.amethyst.model.PublicChatChannel
import com.vitorpamplona.amethyst.model.ServersAvailable
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.service.PackageUtils
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.NewChannelView
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
@@ -1131,7 +1130,7 @@ fun JoinChatButton(accountViewModel: AccountViewModel, channel: Channel, nav: (S
modifier = Modifier.padding(horizontal = 3.dp),
onClick = {
scope.launch(Dispatchers.IO) {
event = accountViewModel.account.follow(channel, !PackageUtils.isAmberInstalled(context))
event = accountViewModel.account.follow(channel, !accountViewModel.loggedInWithAmber())
}
},
shape = ButtonBorder,
@@ -1171,7 +1170,7 @@ fun LeaveChatButton(accountViewModel: AccountViewModel, channel: Channel, nav: (
modifier = Modifier.padding(horizontal = 3.dp),
onClick = {
scope.launch(Dispatchers.IO) {
event = accountViewModel.account.unfollow(channel, !PackageUtils.isAmberInstalled(context))
event = accountViewModel.account.unfollow(channel, !accountViewModel.loggedInWithAmber())
}
},
shape = ButtonBorder,
@@ -1211,7 +1210,7 @@ fun JoinCommunityButton(accountViewModel: AccountViewModel, note: AddressableNot
modifier = Modifier.padding(horizontal = 3.dp),
onClick = {
scope.launch(Dispatchers.IO) {
event = accountViewModel.account.follow(note, !PackageUtils.isAmberInstalled(context))
event = accountViewModel.account.follow(note, !accountViewModel.loggedInWithAmber())
}
},
shape = ButtonBorder,
@@ -1251,7 +1250,7 @@ fun LeaveCommunityButton(accountViewModel: AccountViewModel, note: AddressableNo
modifier = Modifier.padding(horizontal = 3.dp),
onClick = {
scope.launch(Dispatchers.IO) {
event = accountViewModel.account.unfollow(note, !PackageUtils.isAmberInstalled(context))
event = accountViewModel.account.unfollow(note, !accountViewModel.loggedInWithAmber())
}
},
shape = ButtonBorder,

View File

@@ -31,11 +31,15 @@ import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewModel
import com.fonfon.kgeohash.toGeoHash
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.NostrGeohashDataSource
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
import com.vitorpamplona.amethyst.ui.screen.NostrGeoHashFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.RefresheableFeedView
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.quartz.events.Event
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -167,40 +171,65 @@ fun GeoHashActionOptions(
userState?.user?.isFollowingGeohashCached(tag) ?: false
}
}
var event by remember { mutableStateOf<Event?>(null) }
if (event != null) {
SignerDialog(
onClose = {
event = null
},
onPost = {
scope.launch(Dispatchers.IO) {
val signedEvent = Event.fromJson(it)
Client.send(signedEvent)
LocalCache.verifyAndConsume(signedEvent, null)
event = null
}
},
data = event!!.toJson()
)
}
if (isFollowingTag) {
UnfollowButton {
if (!accountViewModel.isWriteable()) {
scope.launch {
Toast
.makeText(
context,
context.getString(R.string.login_with_a_private_key_to_be_able_to_unfollow),
Toast.LENGTH_SHORT
)
.show()
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.unfollowGeohash(tag, false)
} else {
scope.launch {
Toast
.makeText(
context,
context.getString(R.string.login_with_a_private_key_to_be_able_to_unfollow),
Toast.LENGTH_SHORT
)
.show()
}
}
} else {
scope.launch(Dispatchers.IO) {
accountViewModel.account.unfollowGeohash(tag)
accountViewModel.account.unfollowGeohash(tag, true)
}
}
}
} else {
FollowButton {
if (!accountViewModel.isWriteable()) {
scope.launch {
Toast
.makeText(
context,
context.getString(R.string.login_with_a_private_key_to_be_able_to_follow),
Toast.LENGTH_SHORT
)
.show()
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.followGeohash(tag, false)
} else {
scope.launch {
Toast
.makeText(
context,
context.getString(R.string.login_with_a_private_key_to_be_able_to_follow),
Toast.LENGTH_SHORT
)
.show()
}
}
} else {
scope.launch(Dispatchers.IO) {
accountViewModel.account.followGeohash(tag)
accountViewModel.account.followGeohash(tag, true)
}
}
}

View File

@@ -32,7 +32,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.NostrHashtagDataSource
import com.vitorpamplona.amethyst.service.PackageUtils
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.ui.actions.SignerDialog
import com.vitorpamplona.amethyst.ui.screen.NostrHashtagFeedViewModel
@@ -172,7 +171,7 @@ fun HashtagActionOptions(
if (isFollowingTag) {
UnfollowButton {
if (!accountViewModel.isWriteable()) {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.unfollowHashtag(tag, false)
} else {
scope.launch {
@@ -194,7 +193,7 @@ fun HashtagActionOptions(
} else {
FollowButton {
if (!accountViewModel.isWriteable()) {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.followHashtag(tag, false)
} else {
scope.launch {

View File

@@ -791,7 +791,7 @@ private fun DisplayFollowUnfollowButton(
if (isUserFollowingLoggedIn) {
FollowButton(R.string.follow_back) {
if (!accountViewModel.isWriteable()) {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.follow(baseUser, false)
} else {
scope.launch {
@@ -813,7 +813,7 @@ private fun DisplayFollowUnfollowButton(
} else {
FollowButton(R.string.follow) {
if (!accountViewModel.isWriteable()) {
if (PackageUtils.isAmberInstalled(context)) {
if (accountViewModel.loggedInWithAmber()) {
event = accountViewModel.account.follow(baseUser, false)
} else {
scope.launch {

View File

@@ -7,6 +7,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.decodePublicKey
@@ -98,9 +99,8 @@ class ContactListEvent(
followCommunities: List<ATag>,
followEvents: List<String>,
relayUse: Map<String, ReadWrite>?,
privateKey: ByteArray?,
createdAt: Long = TimeUtils.now(),
publicKey: ByteArray? = null
keyPair: KeyPair,
createdAt: Long = TimeUtils.now()
): ContactListEvent {
val content = if (relayUse != null) {
mapper.writeValueAsString(relayUse)
@@ -128,268 +128,149 @@ class ContactListEvent(
listOf("g", it)
}
if (publicKey == null) {
return create(
content = content,
tags = tags,
privateKey = privateKey!!,
createdAt = createdAt
)
}
return create(
content = content,
tags = tags,
pubKey = publicKey.toHexKey(),
keyPair = keyPair,
createdAt = createdAt
)
}
fun followUser(earlierVersion: ContactListEvent, pubKeyHex: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun followUser(earlierVersion: ContactListEvent, pubKeyHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)),
pubKey = pubKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun followUser(earlierVersion: ContactListEvent, pubKeyHex: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)),
privateKey = privateKey,
createdAt = createdAt
)
}
fun unfollowUser(earlierVersion: ContactListEvent, pubKeyHex: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun unfollowUser(earlierVersion: ContactListEvent, pubKeyHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
pubKey = pubKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun unfollowUser(earlierVersion: ContactListEvent, pubKeyHex: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedUser(pubKeyHex)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
privateKey = privateKey,
createdAt = createdAt
)
}
fun followHashtag(earlierVersion: ContactListEvent, hashtag: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun followHashtag(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedHash(hashtag)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("t", hashtag)),
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun followHashtag(earlierVersion: ContactListEvent, hashtag: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedHash(hashtag)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("t", hashtag)),
pubKey = pubKey,
createdAt = createdAt
)
}
fun unfollowHashtag(earlierVersion: ContactListEvent, hashtag: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun unfollowHashtag(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedHash(hashtag)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && !it[1].equals(hashtag, true) },
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun unfollowHashtag(earlierVersion: ContactListEvent, hashtag: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedHash(hashtag)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != hashtag },
pubKey = pubKey,
createdAt = createdAt
)
}
fun followGeohash(earlierVersion: ContactListEvent, hashtag: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun followGeohash(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedGeoHash(hashtag)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("g", hashtag)),
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun unfollowGeohash(earlierVersion: ContactListEvent, hashtag: String, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun unfollowGeohash(earlierVersion: ContactListEvent, hashtag: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedGeoHash(hashtag)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != hashtag },
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun followEvent(earlierVersion: ContactListEvent, idHex: String, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedEvent(idHex)) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("e", idHex)),
pubKey = pubKey,
createdAt = createdAt
)
}
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("e", idHex)),
privateKey = privateKey,
createdAt = createdAt
)
}
fun followEvent(earlierVersion: ContactListEvent, idHex: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun followEvent(earlierVersion: ContactListEvent, idHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedEvent(idHex)) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("e", idHex)),
pubKey = pubKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun unfollowEvent(earlierVersion: ContactListEvent, idHex: String, publicKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun unfollowEvent(earlierVersion: ContactListEvent, idHex: String, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedEvent(idHex)) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex },
pubKey = publicKey,
createdAt = createdAt
)
}
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex },
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)),
pubKey = pubKey,
createdAt = createdAt
)
}
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)),
privateKey = privateKey,
createdAt = createdAt
)
}
fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun followAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)),
pubKey = pubKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun unfollowAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun unfollowAddressableEvent(earlierVersion: ContactListEvent, aTag: ATag, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
if (!earlierVersion.isTaggedAddressableNote(aTag.toTag())) return earlierVersion
if (privateKey == null) {
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() },
pubKey = pubKey,
createdAt = createdAt
)
}
return create(
content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() },
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun updateRelayList(earlierVersion: ContactListEvent, relayUse: Map<String, ReadWrite>?, pubKey: HexKey, privateKey: ByteArray?, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun updateRelayList(earlierVersion: ContactListEvent, relayUse: Map<String, ReadWrite>?, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ContactListEvent {
val content = if (relayUse != null) {
mapper.writeValueAsString(relayUse)
} else {
""
}
if (privateKey == null) {
return create(
content = content,
tags = earlierVersion.tags,
pubKey = pubKey,
createdAt = createdAt
)
}
return create(
content = content,
tags = earlierVersion.tags,
privateKey = privateKey,
keyPair = keyPair,
createdAt = createdAt
)
}
fun create(content: String, tags: List<List<String>>, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ContactListEvent {
fun create(
content: String,
tags: List<List<String>>,
keyPair: KeyPair,
createdAt: Long = TimeUtils.now()
): ContactListEvent {
val pubKey = keyPair.pubKey.toHexKey()
val id = generateId(pubKey, createdAt, kind, tags, content)
return ContactListEvent(id.toHexKey(), pubKey, createdAt, tags, content, "")
}
fun create(content: String, tags: List<List<String>>, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ContactListEvent {
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey)
return ContactListEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
return ContactListEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
}
}