notedeck

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

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(&note_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                     &note_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 }