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