decode.rs (3523B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{ 3 string::{String, ToString}, 4 vec::Vec, 5 }; 6 7 use radroots_events::{RadrootsNostrEvent, geochat::RadrootsGeoChat, kinds::KIND_GEOCHAT}; 8 9 use crate::error::EventParseError; 10 use crate::parsed::{RadrootsParsedData, RadrootsParsedEvent}; 11 12 const DEFAULT_KIND: u32 = KIND_GEOCHAT; 13 const TAG_G: &str = "g"; 14 const TAG_N: &str = "n"; 15 const TAG_T: &str = "t"; 16 const TAG_T_TELEPORT: &str = "teleport"; 17 18 fn parse_geohash_tag(tags: &[Vec<String>]) -> Result<String, EventParseError> { 19 let tag = tags 20 .iter() 21 .find(|t| t.first().map(|s| s.as_str()) == Some(TAG_G)) 22 .ok_or(EventParseError::MissingTag("g"))?; 23 let geohash = tag.get(1).ok_or(EventParseError::InvalidTag("g"))?; 24 if geohash.trim().is_empty() { 25 return Err(EventParseError::InvalidTag("g")); 26 } 27 Ok(geohash.to_string()) 28 } 29 30 fn parse_nickname_tag(tags: &[Vec<String>]) -> Result<Option<String>, EventParseError> { 31 let tag = match tags 32 .iter() 33 .find(|t| t.first().map(|s| s.as_str()) == Some(TAG_N)) 34 { 35 Some(tag) => tag, 36 None => return Ok(None), 37 }; 38 let nickname = tag.get(1).ok_or(EventParseError::InvalidTag("n"))?; 39 if nickname.trim().is_empty() { 40 return Err(EventParseError::InvalidTag("n")); 41 } 42 Ok(Some(nickname.to_string())) 43 } 44 45 fn parse_teleport_tag(tags: &[Vec<String>]) -> Result<bool, EventParseError> { 46 for tag in tags 47 .iter() 48 .filter(|t| t.first().map(|s| s.as_str()) == Some(TAG_T)) 49 { 50 let value = tag.get(1).ok_or(EventParseError::InvalidTag("t"))?; 51 if value.trim().is_empty() { 52 return Err(EventParseError::InvalidTag("t")); 53 } 54 if value.eq_ignore_ascii_case(TAG_T_TELEPORT) { 55 return Ok(true); 56 } 57 } 58 Ok(false) 59 } 60 61 pub fn geochat_from_tags( 62 kind: u32, 63 tags: &[Vec<String>], 64 content: &str, 65 ) -> Result<RadrootsGeoChat, EventParseError> { 66 if kind != DEFAULT_KIND { 67 return Err(EventParseError::InvalidKind { 68 expected: "20000", 69 got: kind, 70 }); 71 } 72 if content.trim().is_empty() { 73 return Err(EventParseError::InvalidTag("content")); 74 } 75 76 let geohash = parse_geohash_tag(tags)?; 77 let nickname = parse_nickname_tag(tags)?; 78 let teleported = parse_teleport_tag(tags)?; 79 80 Ok(RadrootsGeoChat { 81 geohash, 82 content: content.to_string(), 83 nickname, 84 teleported, 85 }) 86 } 87 88 pub fn data_from_event( 89 id: String, 90 author: String, 91 published_at: u32, 92 kind: u32, 93 content: String, 94 tags: Vec<Vec<String>>, 95 ) -> Result<RadrootsParsedData<RadrootsGeoChat>, EventParseError> { 96 let geochat = geochat_from_tags(kind, &tags, &content)?; 97 Ok(RadrootsParsedData::new( 98 id, 99 author, 100 published_at, 101 kind, 102 geochat, 103 )) 104 } 105 106 pub fn parsed_from_event( 107 id: String, 108 author: String, 109 published_at: u32, 110 kind: u32, 111 content: String, 112 tags: Vec<Vec<String>>, 113 sig: String, 114 ) -> Result<RadrootsParsedEvent<RadrootsGeoChat>, EventParseError> { 115 let data = data_from_event( 116 id.clone(), 117 author.clone(), 118 published_at, 119 kind, 120 content.clone(), 121 tags.clone(), 122 )?; 123 Ok(RadrootsParsedEvent { 124 event: RadrootsNostrEvent { 125 id, 126 author, 127 created_at: published_at, 128 kind, 129 content, 130 tags, 131 sig, 132 }, 133 data, 134 }) 135 }