notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 69b260b5c4aa6578a4b58f22b1630c94c348d9c4
parent 53631727d6b773fd11cd4e9c9083648dabc539c7
Author: kernelkind <kernelkind@gmail.com>
Date:   Thu, 18 Dec 2025 17:52:22 -0500

feat(nip17): send conversation message

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Acrates/notedeck_messages/src/nip17/message.rs | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/notedeck_messages/src/nip17/mod.rs | 3+++
2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/crates/notedeck_messages/src/nip17/message.rs b/crates/notedeck_messages/src/nip17/message.rs @@ -0,0 +1,57 @@ +use enostr::ClientMessage; +use notedeck::AppContext; + +use crate::cache::{ConversationCache, ConversationId}; +use crate::nip17::{build_rumor_json, giftwrap_message, OsRng}; + +pub fn send_conversation_message( + conversation_id: ConversationId, + content: String, + cache: &ConversationCache, + ctx: &mut AppContext<'_>, +) { + if content.trim().is_empty() { + return; + } + + let Some(conversation) = cache.get(conversation_id) else { + tracing::warn!("missing conversation {conversation_id} for send action"); + return; + }; + + let Some(selected_kp) = ctx.accounts.selected_filled() else { + tracing::warn!("cannot send message without a full keypair"); + return; + }; + + let Some(rumor_json) = build_rumor_json( + &content, + &conversation.metadata.participants, + selected_kp.pubkey, + ) else { + tracing::error!("failed to build rumor for conversation {conversation_id}"); + return; + }; + + let Some(sender_secret) = ctx.accounts.selected_filled().map(|f| f.secret_key) else { + return; + }; + + let mut rng = OsRng; + for participant in &conversation.metadata.participants { + let Some(giftwrap_json) = + giftwrap_message(&mut rng, sender_secret, participant, &rumor_json) + else { + continue; + }; + if participant == selected_kp.pubkey { + if let Err(e) = ctx.ndb.process_client_event(&giftwrap_json) { + tracing::error!("Could not ingest event: {e:?}"); + } + } + match ClientMessage::event_json(giftwrap_json.clone()) { + Ok(msg) => ctx.pool.send(&msg), + Err(err) => tracing::error!("failed to build client message: {err}"), + }; + } +} diff --git a/crates/notedeck_messages/src/nip17/mod.rs b/crates/notedeck_messages/src/nip17/mod.rs @@ -1,4 +1,7 @@ +pub mod message; + use enostr::{FullKeypair, Pubkey, SecretKey}; +pub use message::send_conversation_message; pub use nostr::secp256k1::rand::rngs::OsRng; use nostr::secp256k1::rand::Rng; use nostr::{