event_ref.rs (5528B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{ 3 string::{String, ToString}, 4 vec::Vec, 5 }; 6 7 use radroots_events::RadrootsNostrEventRef; 8 9 use crate::error::EventParseError; 10 11 fn looks_like_relay_url(s: &str) -> bool { 12 s.starts_with("ws://") || s.starts_with("wss://") 13 } 14 15 pub fn build_event_ref_tag(tag: &str, event: &RadrootsNostrEventRef) -> Vec<String> { 16 let relays_len = event.relays.as_ref().map(|r| r.len()).unwrap_or(0); 17 let mut out = Vec::with_capacity(5 + relays_len); 18 out.push(tag.to_string()); 19 out.push(event.id.clone()); 20 out.push(event.author.clone()); 21 out.push(event.kind.to_string()); 22 out.push(event.d_tag.clone().unwrap_or_default()); 23 if let Some(relays) = &event.relays { 24 out.extend(relays.iter().cloned()); 25 } 26 out 27 } 28 29 pub fn parse_event_ref_tag( 30 tag: &[String], 31 tag_name: &'static str, 32 ) -> Result<RadrootsNostrEventRef, EventParseError> { 33 if tag.first().map(|s| s.as_str()) != Some(tag_name) { 34 return Err(EventParseError::InvalidTag(tag_name)); 35 } 36 let id = tag.get(1).ok_or(EventParseError::InvalidTag(tag_name))?; 37 let author = tag.get(2).ok_or(EventParseError::InvalidTag(tag_name))?; 38 let kind_s = tag.get(3).ok_or(EventParseError::InvalidTag(tag_name))?; 39 let kind: u32 = kind_s 40 .parse() 41 .map_err(|e| EventParseError::InvalidNumber(tag_name, e))?; 42 43 let (d_tag, relays_start) = match tag.get(4) { 44 Some(v) if tag.len() == 5 && looks_like_relay_url(v) => (None, 4), 45 Some(v) if v.is_empty() => (None, 5), 46 Some(v) => (Some(v.clone()), 5), 47 None => (None, 4), 48 }; 49 50 let relays = if tag.len() > relays_start { 51 Some(tag[relays_start..].to_vec()) 52 } else { 53 None 54 }; 55 56 Ok(RadrootsNostrEventRef { 57 id: id.clone(), 58 author: author.clone(), 59 kind, 60 d_tag, 61 relays, 62 }) 63 } 64 65 pub fn find_event_ref_tag<'a>( 66 tags: &'a [Vec<String>], 67 tag_name: &'static str, 68 ) -> Option<&'a Vec<String>> { 69 tags.iter() 70 .find(|t| t.first().map(|s| s.as_str()) == Some(tag_name)) 71 } 72 73 pub fn push_nip10_ref_tags( 74 tags: &mut Vec<Vec<String>>, 75 event: &RadrootsNostrEventRef, 76 tag_e: &'static str, 77 tag_p: &'static str, 78 tag_k: &'static str, 79 tag_a: &'static str, 80 ) { 81 let relays_len = event.relays.as_ref().map(|r| r.len()).unwrap_or(0); 82 let kind_str = event.kind.to_string(); 83 84 let mut e_tag = Vec::with_capacity(2 + relays_len); 85 e_tag.push(tag_e.to_string()); 86 e_tag.push(event.id.clone()); 87 if let Some(relays) = &event.relays { 88 e_tag.extend(relays.iter().cloned()); 89 } 90 tags.push(e_tag); 91 92 let p_tag = vec![tag_p.to_string(), event.author.clone()]; 93 tags.push(p_tag); 94 95 let k_tag = vec![tag_k.to_string(), kind_str.clone()]; 96 tags.push(k_tag); 97 98 if let Some(d_tag) = event.d_tag.as_deref().filter(|v| !v.is_empty()) { 99 let mut addr = String::with_capacity(kind_str.len() + event.author.len() + d_tag.len() + 2); 100 addr.push_str(&kind_str); 101 addr.push(':'); 102 addr.push_str(&event.author); 103 addr.push(':'); 104 addr.push_str(d_tag); 105 106 let mut a_tag = Vec::with_capacity(2 + relays_len); 107 a_tag.push(tag_a.to_string()); 108 a_tag.push(addr); 109 if let Some(relays) = &event.relays { 110 a_tag.extend(relays.iter().cloned()); 111 } 112 tags.push(a_tag); 113 } 114 } 115 116 pub fn parse_nip10_ref_tags( 117 tags: &[Vec<String>], 118 tag_e: &'static str, 119 tag_p: &'static str, 120 tag_k: &'static str, 121 tag_a: &'static str, 122 ) -> Result<RadrootsNostrEventRef, EventParseError> { 123 let e_tag = find_event_ref_tag(tags, tag_e).ok_or(EventParseError::MissingTag(tag_e))?; 124 let id = e_tag.get(1).ok_or(EventParseError::InvalidTag(tag_e))?; 125 if id.trim().is_empty() { 126 return Err(EventParseError::InvalidTag(tag_e)); 127 } 128 let relays = if e_tag.len() > 2 { 129 Some(e_tag[2..].to_vec()) 130 } else { 131 None 132 }; 133 134 let p_tag = find_event_ref_tag(tags, tag_p).ok_or(EventParseError::MissingTag(tag_p))?; 135 let author = p_tag.get(1).ok_or(EventParseError::InvalidTag(tag_p))?; 136 if author.trim().is_empty() { 137 return Err(EventParseError::InvalidTag(tag_p)); 138 } 139 140 let k_tag = find_event_ref_tag(tags, tag_k).ok_or(EventParseError::MissingTag(tag_k))?; 141 let kind_key = k_tag.get(1).ok_or(EventParseError::InvalidTag(tag_k))?; 142 let kind: u32 = kind_key 143 .parse() 144 .map_err(|e| EventParseError::InvalidNumber(tag_k, e))?; 145 146 let mut d_tag: Option<String> = None; 147 let mut addr_relays: Option<Vec<String>> = None; 148 for tag in tags 149 .iter() 150 .filter(|t| t.first().map(|s| s.as_str()) == Some(tag_a)) 151 { 152 let value = match tag.get(1) { 153 Some(v) => v, 154 None => continue, 155 }; 156 let mut parts = value.splitn(3, ':'); 157 let kind_part = parts.next(); 158 let author_part = parts.next(); 159 let d_part = parts.next(); 160 if kind_part != Some(kind_key.as_str()) || author_part != Some(author.as_str()) { 161 continue; 162 } 163 if let Some(d) = d_part 164 && !d.is_empty() 165 { 166 d_tag = Some(d.to_string()); 167 } 168 if tag.len() > 2 { 169 addr_relays = Some(tag[2..].to_vec()); 170 } 171 break; 172 } 173 174 let relays = relays.or(addr_relays); 175 176 Ok(RadrootsNostrEventRef { 177 id: id.clone(), 178 author: author.clone(), 179 kind, 180 d_tag, 181 relays, 182 }) 183 }