event.rs (4390B)
1 use radroots_events_codec::job::traits::{JobEventBorrow, JobEventLike}; 2 use radroots_nostr::prelude::{RadrootsNostrEvent, RadrootsNostrKind}; 3 4 #[derive(Clone, Debug)] 5 pub struct NostrEventAdapter<'a> { 6 evt: &'a RadrootsNostrEvent, 7 id_hex: String, 8 author_hex: String, 9 } 10 11 impl<'a> NostrEventAdapter<'a> { 12 #[inline] 13 pub fn new(evt: &'a RadrootsNostrEvent) -> Self { 14 Self { 15 evt, 16 id_hex: evt.id.to_hex(), 17 author_hex: evt.pubkey.to_string(), 18 } 19 } 20 21 #[inline] 22 fn tags_as_slices(&self) -> Vec<Vec<String>> { 23 self.evt 24 .tags 25 .iter() 26 .map(|t| t.as_slice().to_vec()) 27 .collect() 28 } 29 } 30 31 impl<'a> JobEventBorrow<'a> for NostrEventAdapter<'a> { 32 #[inline] 33 fn raw_id(&'a self) -> &'a str { 34 &self.id_hex 35 } 36 #[inline] 37 fn raw_author(&'a self) -> &'a str { 38 &self.author_hex 39 } 40 #[inline] 41 fn raw_content(&'a self) -> &'a str { 42 &self.evt.content 43 } 44 #[inline] 45 fn raw_kind(&'a self) -> u32 { 46 match self.evt.kind { 47 RadrootsNostrKind::Custom(v) => v as u32, 48 _ => 0, 49 } 50 } 51 } 52 53 impl JobEventLike for NostrEventAdapter<'_> { 54 fn raw_id(&self) -> String { 55 self.id_hex.clone() 56 } 57 fn raw_author(&self) -> String { 58 self.author_hex.clone() 59 } 60 fn raw_published_at(&self) -> u32 { 61 self.evt.created_at.as_secs() as u32 62 } 63 fn raw_kind(&self) -> u32 { 64 match self.evt.kind { 65 RadrootsNostrKind::Custom(v) => v as u32, 66 _ => 0, 67 } 68 } 69 fn raw_content(&self) -> String { 70 self.evt.content.clone() 71 } 72 fn raw_tags(&self) -> Vec<Vec<String>> { 73 self.tags_as_slices() 74 } 75 fn raw_sig(&self) -> String { 76 self.evt.sig.to_string() 77 } 78 } 79 80 #[cfg(test)] 81 #[cfg_attr(coverage_nightly, coverage(off))] 82 mod tests { 83 use super::NostrEventAdapter; 84 use radroots_events_codec::job::traits::{JobEventBorrow, JobEventLike}; 85 use radroots_nostr::prelude::{ 86 RadrootsNostrEvent, RadrootsNostrEventBuilder, RadrootsNostrKeys, RadrootsNostrKind, 87 RadrootsNostrTag, RadrootsNostrTagKind, 88 }; 89 90 fn build_event( 91 keys: &RadrootsNostrKeys, 92 kind: RadrootsNostrKind, 93 tags: Vec<RadrootsNostrTag>, 94 ) -> RadrootsNostrEvent { 95 RadrootsNostrEventBuilder::new(kind, "content") 96 .tags(tags) 97 .sign_with_keys(keys) 98 .expect("event must sign") 99 } 100 101 #[test] 102 fn adapter_exposes_borrow_and_owned_fields_for_custom_kind() { 103 let keys = RadrootsNostrKeys::generate(); 104 let recipient = RadrootsNostrKeys::generate(); 105 let recipient_hex = recipient.public_key().to_hex(); 106 let tags = vec![RadrootsNostrTag::custom( 107 RadrootsNostrTagKind::p(), 108 vec![recipient_hex.clone()], 109 )]; 110 let event = build_event(&keys, RadrootsNostrKind::Custom(5322), tags); 111 let adapter = NostrEventAdapter::new(&event); 112 113 assert_eq!(JobEventBorrow::raw_id(&adapter), event.id.to_hex()); 114 assert_eq!( 115 JobEventBorrow::raw_author(&adapter), 116 event.pubkey.to_string() 117 ); 118 assert_eq!(JobEventBorrow::raw_content(&adapter), "content"); 119 assert_eq!(JobEventBorrow::raw_kind(&adapter), 5322); 120 121 assert_eq!(JobEventLike::raw_id(&adapter), event.id.to_hex()); 122 assert_eq!(JobEventLike::raw_author(&adapter), event.pubkey.to_string()); 123 assert_eq!(JobEventLike::raw_content(&adapter), "content".to_string()); 124 assert_eq!(JobEventLike::raw_kind(&adapter), 5322); 125 assert_eq!( 126 JobEventLike::raw_tags(&adapter), 127 vec![vec!["p".to_string(), recipient_hex]] 128 ); 129 assert_eq!(JobEventLike::raw_sig(&adapter), event.sig.to_string()); 130 } 131 132 #[test] 133 fn adapter_maps_non_custom_kind_to_zero() { 134 let keys = RadrootsNostrKeys::generate(); 135 let event = build_event(&keys, RadrootsNostrKind::TextNote, Vec::new()); 136 let adapter = NostrEventAdapter::new(&event); 137 138 assert_eq!(JobEventBorrow::raw_kind(&adapter), 0); 139 assert_eq!(JobEventLike::raw_kind(&adapter), 0); 140 assert_eq!( 141 JobEventLike::raw_published_at(&adapter), 142 event.created_at.as_secs() as u32 143 ); 144 } 145 }