decode.rs (2668B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{string::String, vec::Vec}; 3 4 use radroots_event::{ 5 envelope::kind::KIND_FOLLOW, 6 social::follow::{Follow, FollowProfile}, 7 }; 8 9 use crate::error::EventParseError; 10 use crate::parsed::{RadrootsParsedData, RadrootsParsedEvent}; 11 12 const DEFAULT_KIND: u32 = KIND_FOLLOW; 13 14 fn looks_like_ws_relay(s: &str) -> bool { 15 s.starts_with("ws://") || s.starts_with("wss://") 16 } 17 18 fn parse_follow_tag(tag: &[String], published_at: u64) -> Result<FollowProfile, EventParseError> { 19 let public_key = tag.get(1).ok_or(EventParseError::InvalidTag("p"))?; 20 let (relay_url, contact_name) = match tag.get(2).filter(|s| !s.is_empty()) { 21 Some(value) if looks_like_ws_relay(value) => ( 22 Some(value.clone()), 23 tag.get(3).filter(|s| !s.is_empty()).cloned(), 24 ), 25 Some(value) => (None, Some(value.clone())), 26 None => (None, tag.get(3).filter(|s| !s.is_empty()).cloned()), 27 }; 28 29 let published_at = match tag.get(4) { 30 Some(v) => v 31 .parse() 32 .map_err(|e| EventParseError::InvalidNumber("p", e))?, 33 None => published_at, 34 }; 35 36 Ok(FollowProfile { 37 published_at, 38 public_key: public_key.clone(), 39 relay_url, 40 contact_name, 41 }) 42 } 43 44 pub fn follow_from_tags( 45 kind: u32, 46 tags: &[Vec<String>], 47 published_at: u64, 48 ) -> Result<Follow, EventParseError> { 49 if kind != DEFAULT_KIND { 50 return Err(EventParseError::InvalidKind { 51 expected: "3", 52 got: kind, 53 }); 54 } 55 let mut list = Vec::new(); 56 for tag in tags 57 .iter() 58 .filter(|t| t.first().map(|s| s.as_str()) == Some("p")) 59 { 60 list.push(parse_follow_tag(tag, published_at)?); 61 } 62 Ok(Follow { list }) 63 } 64 65 pub fn data_from_event( 66 id: String, 67 author: String, 68 published_at: u64, 69 kind: u32, 70 _content: String, 71 tags: Vec<Vec<String>>, 72 ) -> Result<RadrootsParsedData<Follow>, EventParseError> { 73 let follow = follow_from_tags(kind, &tags, published_at)?; 74 Ok(RadrootsParsedData::new( 75 id, 76 author, 77 published_at, 78 kind, 79 follow, 80 )) 81 } 82 83 pub fn parsed_from_event( 84 id: String, 85 author: String, 86 published_at: u64, 87 kind: u32, 88 content: String, 89 tags: Vec<Vec<String>>, 90 sig: String, 91 ) -> Result<RadrootsParsedEvent<Follow>, EventParseError> { 92 let data = data_from_event( 93 id.clone(), 94 author.clone(), 95 published_at, 96 kind, 97 content.clone(), 98 tags.clone(), 99 )?; 100 RadrootsParsedEvent::from_event_parts(id, author, published_at, kind, content, tags, sig, data) 101 }