repost.rs (3190B)
1 use enostr::{Keypair, NoteId, RelayPool}; 2 use nostrdb::{Ndb, Note, NoteBuilder, Transaction}; 3 4 use crate::{nav::RouterAction, Route}; 5 6 pub fn generate_repost_event<'a>( 7 ndb: &'a Ndb, 8 noteid_to_repost: &NoteId, 9 signer_nsec: &[u8; 32], 10 pool: &RelayPool, 11 ) -> Result<Note<'a>, String> { 12 let txn = Transaction::new(ndb).expect("txn"); 13 let note_to_repost = ndb 14 .get_note_by_id(&txn, noteid_to_repost.bytes()) 15 .map_err(|e| format!("could not find note to repost {noteid_to_repost:?}: {e}"))?; 16 17 if note_to_repost.kind() != 1 { 18 return Err(format!( 19 "trying to generate a kind 6 repost but the kind is not 1 (it's {})", 20 note_to_repost.kind() 21 )); 22 } 23 24 let urls = pool.urls(); 25 let Some(relay) = urls.first() else { 26 return Err( 27 "relay pool does not have any relays. This makes meeting the repost spec impossible" 28 .to_owned(), 29 ); 30 }; 31 32 let note_to_repost_content = note_to_repost 33 .json() 34 .map_err(|e| format!("could not convert note {note_to_repost:?} to json: {e}"))?; 35 36 NoteBuilder::new() 37 .content(¬e_to_repost_content) 38 .kind(6) 39 .start_tag() 40 .tag_str("e") 41 .tag_id(note_to_repost.id()) 42 .tag_str(relay) 43 .start_tag() 44 .tag_str("p") 45 .tag_id(note_to_repost.pubkey()) 46 .sign(signer_nsec) 47 .build() 48 .ok_or("Failure in NoteBuilder::build".to_owned()) 49 } 50 51 pub enum RepostAction { 52 Kind06Repost(NoteId), 53 Quote(NoteId), 54 Cancel, 55 } 56 57 impl RepostAction { 58 pub fn process( 59 self, 60 ndb: &nostrdb::Ndb, 61 current_user: &Keypair, 62 pool: &mut RelayPool, 63 ) -> Option<RouterAction> { 64 match self { 65 RepostAction::Quote(note_id) => { 66 Some(RouterAction::CloseSheetThenRoute(Route::quote(note_id))) 67 } 68 RepostAction::Kind06Repost(note_id) => { 69 let Some(full_user) = current_user.to_full() else { 70 tracing::error!("Attempting to make a kind 6 repost, but we don't have nsec"); 71 return None; 72 }; 73 74 let repost_ev = generate_repost_event( 75 ndb, 76 ¬e_id, 77 &full_user.secret_key.secret_bytes(), 78 pool, 79 ) 80 .inspect_err(|e| tracing::error!("failure to generate repost event: {e}")) 81 .ok()?; 82 83 let Ok(event) = &enostr::ClientMessage::event(&repost_ev) else { 84 tracing::error!("send_note_builder: failed to build json"); 85 return None; 86 }; 87 88 let Ok(json) = event.to_json() else { 89 tracing::error!("send_note_builder: failed to build json"); 90 return None; 91 }; 92 93 let _ = ndb.process_event_with(&json, nostrdb::IngestMetadata::new().client(true)); 94 95 pool.send(event); 96 97 Some(RouterAction::GoBack) 98 } 99 RepostAction::Cancel => Some(RouterAction::GoBack), 100 } 101 } 102 }