post.rs (3147B)
1 use enostr::FullKeypair; 2 use nostrdb::{Note, NoteBuilder, NoteReply}; 3 use std::collections::HashSet; 4 5 pub struct NewPost { 6 pub content: String, 7 pub account: FullKeypair, 8 } 9 10 impl NewPost { 11 pub fn new(content: String, account: FullKeypair) -> Self { 12 NewPost { content, account } 13 } 14 15 pub fn to_note(&self, seckey: &[u8; 32]) -> Note { 16 NoteBuilder::new() 17 .kind(1) 18 .content(&self.content) 19 .sign(seckey) 20 .build() 21 .expect("note should be ok") 22 } 23 24 pub fn to_reply(&self, seckey: &[u8; 32], replying_to: &Note) -> Note { 25 let builder = NoteBuilder::new().kind(1).content(&self.content); 26 27 let nip10 = NoteReply::new(replying_to.tags()); 28 29 let mut builder = if let Some(root) = nip10.root() { 30 builder 31 .start_tag() 32 .tag_str("e") 33 .tag_str(&hex::encode(root.id)) 34 .tag_str("") 35 .tag_str("root") 36 .start_tag() 37 .tag_str("e") 38 .tag_str(&hex::encode(replying_to.id())) 39 .tag_str("") 40 .tag_str("reply") 41 .sign(seckey) 42 } else { 43 // we're replying to a post that isn't in a thread, 44 // just add a single reply-to-root tag 45 builder 46 .start_tag() 47 .tag_str("e") 48 .tag_str(&hex::encode(replying_to.id())) 49 .tag_str("") 50 .tag_str("root") 51 .sign(seckey) 52 }; 53 54 let mut seen_p: HashSet<&[u8; 32]> = HashSet::new(); 55 56 builder = builder 57 .start_tag() 58 .tag_str("p") 59 .tag_str(&hex::encode(replying_to.pubkey())); 60 61 seen_p.insert(replying_to.pubkey()); 62 63 for tag in replying_to.tags() { 64 if tag.count() < 2 { 65 continue; 66 } 67 68 if tag.get_unchecked(0).variant().str() != Some("p") { 69 continue; 70 } 71 72 let id = if let Some(id) = tag.get_unchecked(1).variant().id() { 73 id 74 } else { 75 continue; 76 }; 77 78 if seen_p.contains(id) { 79 continue; 80 } 81 82 seen_p.insert(id); 83 84 builder = builder.start_tag().tag_str("p").tag_str(&hex::encode(id)); 85 } 86 87 builder 88 .sign(seckey) 89 .build() 90 .expect("expected build to work") 91 } 92 93 pub fn to_quote(&self, seckey: &[u8; 32], quoting: &Note) -> Note { 94 let new_content = format!( 95 "{}\nnostr:{}", 96 self.content, 97 enostr::NoteId::new(*quoting.id()).to_bech().unwrap() 98 ); 99 100 NoteBuilder::new() 101 .kind(1) 102 .content(&new_content) 103 .start_tag() 104 .tag_str("q") 105 .tag_str(&hex::encode(quoting.id())) 106 .start_tag() 107 .tag_str("p") 108 .tag_str(&hex::encode(quoting.pubkey())) 109 .sign(seckey) 110 .build() 111 .expect("expected build to work") 112 } 113 }