diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 93377915a..d6663ac4e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -833,9 +833,10 @@ class Account( root: String?, directMentions: Set, relayList: List? = null, - geohash: String? = null - ) { - if (!isWriteable()) return + geohash: String? = null, + signEvent: Boolean = true + ): TextNoteEvent? { + if (!isWriteable() && signEvent) return null val repliesToHex = replyTo?.filter { it.address() == null }?.map { it.idHex } val mentionsHex = mentions?.map { it.pubkeyHex } @@ -854,11 +855,17 @@ class Account( root = root, directMentions = directMentions, geohash = geohash, - privateKey = keyPair.privKey!! + pubKey = keyPair.pubKey.toHexKey(), + privateKey = keyPair.privKey ) + if (!signEvent) { + return signedEvent + } + Client.send(signedEvent, relayList = relayList) LocalCache.consume(signedEvent) + return null } fun sendPoll( @@ -874,9 +881,10 @@ class Account( wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, relayList: List? = null, - geohash: String? = null - ) { - if (!isWriteable()) return + geohash: String? = null, + signEvent: Boolean = true + ): PollNoteEvent? { + if (!isWriteable() && signEvent) return null val repliesToHex = replyTo?.map { it.idHex } val mentionsHex = mentions?.map { it.pubkeyHex } @@ -887,7 +895,8 @@ class Account( replyTos = repliesToHex, mentions = mentionsHex, addresses = addresses, - privateKey = keyPair.privKey!!, + pubKey = keyPair.pubKey.toHexKey(), + privateKey = keyPair.privKey, pollOptions = pollOptions, valueMaximum = valueMaximum, valueMinimum = valueMinimum, @@ -899,12 +908,28 @@ class Account( geohash = geohash ) // println("Sending new PollNoteEvent: %s".format(signedEvent.toJson())) + + if (!signEvent) { + return signedEvent + } + Client.send(signedEvent, relayList = relayList) LocalCache.consume(signedEvent) + return null } - fun sendChannelMessage(message: String, toChannel: String, replyTo: List?, mentions: List?, zapReceiver: String? = null, wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, geohash: String? = null) { - if (!isWriteable()) return + fun sendChannelMessage( + message: String, + toChannel: String, + replyTo: List?, + mentions: List?, + zapReceiver: String? = null, + wantsToMarkAsSensitive: Boolean, + zapRaiserAmount: Long? = null, + geohash: String? = null, + signEvent: Boolean = true + ): ChannelMessageEvent? { + if (!isWriteable() && signEvent) return null // val repliesToHex = listOfNotNull(replyingTo?.idHex).ifEmpty { null } val repliesToHex = replyTo?.map { it.idHex } @@ -919,14 +944,31 @@ class Account( markAsSensitive = wantsToMarkAsSensitive, zapRaiserAmount = zapRaiserAmount, geohash = geohash, - privateKey = keyPair.privKey!! + pubKey = keyPair.pubKey.toHexKey(), + privateKey = keyPair.privKey ) + + if (!signEvent) { + return signedEvent + } + Client.send(signedEvent) LocalCache.consume(signedEvent, null) + return null } - fun sendLiveMessage(message: String, toChannel: ATag, replyTo: List?, mentions: List?, zapReceiver: String? = null, wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, geohash: String? = null) { - if (!isWriteable()) return + fun sendLiveMessage( + message: String, + toChannel: ATag, + replyTo: List?, + mentions: List?, + zapReceiver: String? = null, + wantsToMarkAsSensitive: Boolean, + zapRaiserAmount: Long? = null, + geohash: String? = null, + signEvent: Boolean = true + ): LiveActivitiesChatMessageEvent? { + if (!isWriteable() && signEvent) return null // val repliesToHex = listOfNotNull(replyingTo?.idHex).ifEmpty { null } val repliesToHex = replyTo?.map { it.idHex } @@ -941,18 +983,35 @@ class Account( markAsSensitive = wantsToMarkAsSensitive, zapRaiserAmount = zapRaiserAmount, geohash = geohash, - privateKey = keyPair.privKey!! + pubKey = keyPair.pubKey.toHexKey(), + privateKey = keyPair.privKey ) + + if (!signEvent) { + return signedEvent + } + Client.send(signedEvent) LocalCache.consume(signedEvent, null) + return null } - fun sendPrivateMessage(message: String, toUser: User, replyingTo: Note? = null, mentions: List?, zapReceiver: String? = null, wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, geohash: String? = null) { - sendPrivateMessage(message, toUser.pubkeyHex, replyingTo, mentions, zapReceiver, wantsToMarkAsSensitive, zapRaiserAmount, geohash) + fun sendPrivateMessage(message: String, toUser: User, replyingTo: Note? = null, mentions: List?, zapReceiver: String? = null, wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, geohash: String? = null): PrivateDmEvent? { + return sendPrivateMessage(message, toUser.pubkeyHex, replyingTo, mentions, zapReceiver, wantsToMarkAsSensitive, zapRaiserAmount, geohash) } - fun sendPrivateMessage(message: String, toUser: HexKey, replyingTo: Note? = null, mentions: List?, zapReceiver: String? = null, wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, geohash: String? = null) { - if (!isWriteable()) return + fun sendPrivateMessage( + message: String, + toUser: HexKey, + replyingTo: Note? = null, + mentions: List?, + zapReceiver: String? = null, + wantsToMarkAsSensitive: Boolean, + zapRaiserAmount: Long? = null, + geohash: String? = null, + signEvent: Boolean = true + ): PrivateDmEvent? { + if (!isWriteable() && signEvent) return null val repliesToHex = listOfNotNull(replyingTo?.idHex).ifEmpty { null } val mentionsHex = mentions?.map { it.pubkeyHex } @@ -970,8 +1029,14 @@ class Account( privateKey = keyPair.privKey!!, advertiseNip18 = false ) + + if (!signEvent) { + return signedEvent + } + Client.send(signedEvent) LocalCache.consume(signedEvent, null) + return null } fun sendNIP24PrivateMessage( @@ -983,9 +1048,10 @@ class Account( zapReceiver: String? = null, wantsToMarkAsSensitive: Boolean, zapRaiserAmount: Long? = null, - geohash: String? = null - ) { - if (!isWriteable()) return + geohash: String? = null, + signEvent: Boolean = true + ): List? { + if (!isWriteable() && signEvent) return null val repliesToHex = listOfNotNull(replyingTo?.idHex).ifEmpty { null } val mentionsHex = mentions?.map { it.pubkeyHex } @@ -1003,7 +1069,12 @@ class Account( from = keyPair.privKey!! ) + if (!signEvent) { + return signedEvents + } + broadcastPrivately(signedEvents) + return null } fun broadcastPrivately(signedEvents: List) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelMessageEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelMessageEvent.kt index c38eed35e..583350cb2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelMessageEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ChannelMessageEvent.kt @@ -33,14 +33,14 @@ class ChannelMessageEvent( replyTos: List? = null, mentions: List? = null, zapReceiver: String?, - privateKey: ByteArray, + pubKey: HexKey, + privateKey: ByteArray?, createdAt: Long = TimeUtils.now(), markAsSensitive: Boolean, zapRaiserAmount: Long?, geohash: String? = null ): ChannelMessageEvent { val content = message - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() val tags = mutableListOf( listOf("e", channel, "", "root") ) @@ -64,8 +64,8 @@ class ChannelMessageEvent( } val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return ChannelMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) + val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) + return ChannelMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/LiveActivitiesChatMessageEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/LiveActivitiesChatMessageEvent.kt index 4b85e0c33..dc4031159 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/LiveActivitiesChatMessageEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/LiveActivitiesChatMessageEvent.kt @@ -48,14 +48,14 @@ class LiveActivitiesChatMessageEvent( replyTos: List? = null, mentions: List? = null, zapReceiver: String?, - privateKey: ByteArray, + pubKey: HexKey, + privateKey: ByteArray?, createdAt: Long = TimeUtils.now(), markAsSensitive: Boolean, zapRaiserAmount: Long?, geohash: String? = null ): LiveActivitiesChatMessageEvent { val content = message - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() val tags = mutableListOf( listOf("a", activity.toTag(), "", "root") ) @@ -79,8 +79,8 @@ class LiveActivitiesChatMessageEvent( } val id = generateId(pubKey, createdAt, kind, tags, content) - val sig = CryptoUtils.sign(id, privateKey) - return LiveActivitiesChatMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) + val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) + return LiveActivitiesChatMessageEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "") } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/PollNoteEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/PollNoteEvent.kt index 3eb33b5be..5195df73e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/PollNoteEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/PollNoteEvent.kt @@ -44,7 +44,8 @@ class PollNoteEvent( replyTos: List?, mentions: List?, addresses: List?, - privateKey: ByteArray, + pubKey: HexKey, + privateKey: ByteArray?, createdAt: Long = TimeUtils.now(), pollOptions: Map, valueMaximum: Int?, @@ -56,7 +57,6 @@ class PollNoteEvent( zapRaiserAmount: Long?, geohash: String? = null ): PollNoteEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() val tags = mutableListOf>() replyTos?.forEach { tags.add(listOf("e", it)) @@ -89,8 +89,8 @@ class PollNoteEvent( } val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = CryptoUtils.sign(id, privateKey) - return PollNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig.toHexKey()) + val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) + return PollNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/TextNoteEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/TextNoteEvent.kt index 3eb72ca05..b0074adf2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/TextNoteEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/TextNoteEvent.kt @@ -37,11 +37,10 @@ class TextNoteEvent( root: String?, directMentions: Set, geohash: String? = null, - - privateKey: ByteArray, + pubKey: HexKey, + privateKey: ByteArray?, createdAt: Long = TimeUtils.now() ): TextNoteEvent { - val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() val tags = mutableListOf>() replyTos?.forEach { if (it == replyingTo) { @@ -97,8 +96,8 @@ class TextNoteEvent( } val id = generateId(pubKey, createdAt, kind, tags, msg) - val sig = CryptoUtils.sign(id, privateKey) - return TextNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig.toHexKey()) + val sig = if (privateKey == null) null else CryptoUtils.sign(id, privateKey) + return TextNoteEvent(id.toHexKey(), pubKey, createdAt, tags, msg, sig?.toHexKey() ?: "") } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt index 19d3b977b..91c0b16bc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostView.kt @@ -75,12 +75,15 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.ServersAvailable import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil +import com.vitorpamplona.amethyst.service.model.Event import com.vitorpamplona.amethyst.service.noProtocolUrlValidator +import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.components.* import com.vitorpamplona.amethyst.ui.note.CancelIcon import com.vitorpamplona.amethyst.ui.note.CloseIcon @@ -158,6 +161,24 @@ fun NewPostView( } } + var event by remember { mutableStateOf(null) } + if (event != null) { + SignerDialog( + onClose = { + event = null + }, + onPost = { + scope.launch(Dispatchers.IO) { + Client.send(it, relayList = relayList) + LocalCache.verifyAndConsume(it, null) + event = null + onClose() + } + }, + event = event!! + ) + } + Dialog( onDismissRequest = { onClose() }, properties = DialogProperties( @@ -224,8 +245,10 @@ fun NewPostView( PostButton( onPost = { scope.launch(Dispatchers.IO) { - postViewModel.sendPost(relayList = relayList) - onClose() + event = postViewModel.sendPost(relayList = relayList, signEvent = account.keyPair.privKey != null) + if (event == null) { + onClose() + } } }, isActive = postViewModel.canPost() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt index 53ab62161..ae048ccef 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt @@ -22,6 +22,7 @@ import com.vitorpamplona.amethyst.service.model.AddressableEvent import com.vitorpamplona.amethyst.service.model.BaseTextNoteEvent import com.vitorpamplona.amethyst.service.model.ChatMessageEvent import com.vitorpamplona.amethyst.service.model.CommunityDefinitionEvent +import com.vitorpamplona.amethyst.service.model.Event import com.vitorpamplona.amethyst.service.model.PrivateDmEvent import com.vitorpamplona.amethyst.service.model.TextNoteEvent import com.vitorpamplona.amethyst.service.noProtocolUrlValidator @@ -156,7 +157,7 @@ open class NewPostViewModel() : ViewModel() { this.account = account } - fun sendPost(relayList: List? = null) { + fun sendPost(relayList: List? = null, signEvent: Boolean = true): Event? { val tagger = NewMessageTagger(message.text, mentions, replyTos, originalNote?.channelHex()) tagger.run()