From 2d96f009c00a226d295d16dc796b1e2e1fcebc53 Mon Sep 17 00:00:00 2001 From: Yuki Kishimoto Date: Thu, 14 Mar 2024 11:14:50 +0100 Subject: [PATCH] nostr: add `EventBuilder::text_note_reply` Closes https://github.com/rust-nostr/nostr/issues/333 --- bindings/nostr-ffi/src/event/builder.rs | 22 +++++++ bindings/nostr-js/src/event/builder.rs | 22 +++++++ crates/nostr/src/event/builder.rs | 76 +++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/bindings/nostr-ffi/src/event/builder.rs b/bindings/nostr-ffi/src/event/builder.rs index fb9f434a9..cf19e7110 100644 --- a/bindings/nostr-ffi/src/event/builder.rs +++ b/bindings/nostr-ffi/src/event/builder.rs @@ -109,6 +109,28 @@ impl EventBuilder { }) } + /// Text note reply + /// + /// If no `root` is passed, the `rely_to` will be used for root `e` tag. + /// + /// + #[uniffi::constructor] + pub fn text_note_reply( + content: String, + reply_to: &Event, + root: Option>, + relay_url: Option, + ) -> Self { + Self { + inner: nostr::EventBuilder::text_note_reply( + content, + reply_to.deref(), + root.as_ref().map(|e| e.as_ref().deref()), + relay_url.map(UncheckedUrl::from), + ), + } + } + #[uniffi::constructor] pub fn long_form_text_note(content: &str, tags: &[Arc]) -> Result { let tags = tags.iter().map(|t| t.as_ref().deref().clone()); diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 026a1c384..008ba8006 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -112,6 +112,28 @@ impl JsEventBuilder { } } + /// Text note reply + /// + /// If no `root` is passed, the `rely_to` will be used for root `e` tag. + /// + /// + #[wasm_bindgen(js_name = textNoteReply)] + pub fn text_note_reply( + content: &str, + reply_to: &JsEvent, + root: Option, + relay_url: Option, + ) -> Self { + Self { + builder: EventBuilder::text_note_reply( + content, + reply_to.deref(), + root.as_deref(), + relay_url.map(UncheckedUrl::from), + ), + } + } + #[wasm_bindgen(js_name = longFormTextNote)] pub fn long_form_text_note(content: &str, tags: Vec) -> Self { Self { diff --git a/crates/nostr/src/event/builder.rs b/crates/nostr/src/event/builder.rs index 5337a907a..bbb3de37b 100644 --- a/crates/nostr/src/event/builder.rs +++ b/crates/nostr/src/event/builder.rs @@ -396,6 +396,82 @@ impl EventBuilder { Self::new(Kind::TextNote, content, tags) } + /// Text note reply + /// + /// If no `root` is passed, the `rely_to` will be used for root `e` tag. + /// + /// + pub fn text_note_reply( + content: S, + reply_to: &Event, + root: Option<&Event>, + relay_url: Option, + ) -> Self + where + S: Into, + { + let mut tags: Vec = Vec::new(); + + // Add `e` and `p` tag of **root** event + match root { + Some(root) => { + // ID and author + tags.push(Tag::Event { + event_id: root.id(), + relay_url: relay_url.clone(), + marker: Some(Marker::Root), + }); + tags.push(Tag::public_key(root.author())); + + // Add others `p` tags + tags.extend( + root.iter_tags() + .filter(|t| { + t.kind() + == TagKind::SingleLetter(SingleLetterTag { + character: Alphabet::P, + uppercase: false, + }) + }) + .cloned(), + ); + } + None => { + // No root event is passed, use `reply_to` event ID for `root` marker + tags.push(Tag::Event { + event_id: reply_to.id(), + relay_url: relay_url.clone(), + marker: Some(Marker::Root), + }); + } + } + + // Add `e` and `p` tag of event author + tags.push(Tag::Event { + event_id: reply_to.id(), + relay_url, + marker: Some(Marker::Reply), + }); + tags.push(Tag::public_key(reply_to.author())); + + // Add others `p` tags of reply_to event + tags.extend( + reply_to + .iter_tags() + .filter(|t| { + t.kind() + == TagKind::SingleLetter(SingleLetterTag { + character: Alphabet::P, + uppercase: false, + }) + }) + .cloned(), + ); + + // Compose event + Self::new(Kind::TextNote, content, tags) + } + /// Long-form text note (generally referred to as "articles" or "blog posts"). /// ///