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