decode.rs (3279B)
1 #[cfg(not(feature = "std"))] 2 use alloc::{ 3 string::{String, ToString}, 4 vec::Vec, 5 }; 6 7 use radroots_event::{ 8 envelope::kind::{KIND_ARTICLE, KIND_FARM}, 9 farm::FarmRef, 10 post::article::Article, 11 social::SocialFarmAnchor, 12 tag::name::{TAG_A, TAG_D, TAG_IMAGE, TAG_PUBLISHED_AT, TAG_SUMMARY, TAG_T, TAG_TITLE}, 13 }; 14 15 use crate::d_tag::validate_d_tag_tag; 16 use crate::error::EventParseError; 17 use crate::field_helpers::{ 18 parse_address_tag_with_kind, required_tag_value, tag_values, validate_non_empty_tag_value, 19 }; 20 use crate::parsed::{RadrootsParsedData, RadrootsParsedEvent}; 21 use crate::social_helpers::{first_tag_value, location_from_tags}; 22 23 const EXPECTED_KIND: &str = "30023"; 24 25 pub fn article_from_event( 26 kind: u32, 27 tags: &[Vec<String>], 28 content: &str, 29 ) -> Result<Article, EventParseError> { 30 if kind != KIND_ARTICLE { 31 return Err(EventParseError::InvalidKind { 32 expected: EXPECTED_KIND, 33 got: kind, 34 }); 35 } 36 validate_non_empty_tag_value(content, "content")?; 37 let d_tag = required_tag_value(tags, TAG_D)?; 38 validate_d_tag_tag(&d_tag, TAG_D)?; 39 let title = required_tag_value(tags, TAG_TITLE)?; 40 let published_at = first_tag_value(tags, TAG_PUBLISHED_AT) 41 .map(|value| { 42 value 43 .parse::<u64>() 44 .map_err(|err| EventParseError::InvalidNumber(TAG_PUBLISHED_AT, err)) 45 }) 46 .transpose()?; 47 let farm = parse_farm_anchor(tags)?; 48 Ok(Article { 49 d_tag, 50 title, 51 content: content.to_string(), 52 summary: first_tag_value(tags, TAG_SUMMARY), 53 image: first_tag_value(tags, TAG_IMAGE), 54 published_at, 55 farm, 56 location: location_from_tags(tags), 57 topics: non_empty_vec(tag_values(tags, TAG_T)?), 58 }) 59 } 60 61 pub fn data_from_event( 62 id: String, 63 author: String, 64 published_at: u64, 65 kind: u32, 66 content: String, 67 tags: Vec<Vec<String>>, 68 ) -> Result<RadrootsParsedData<Article>, EventParseError> { 69 let article = article_from_event(kind, &tags, &content)?; 70 Ok(RadrootsParsedData::new( 71 id, 72 author, 73 published_at, 74 kind, 75 article, 76 )) 77 } 78 79 pub fn parsed_from_event( 80 id: String, 81 author: String, 82 published_at: u64, 83 kind: u32, 84 content: String, 85 tags: Vec<Vec<String>>, 86 sig: String, 87 ) -> Result<RadrootsParsedEvent<Article>, EventParseError> { 88 let data = data_from_event( 89 id.clone(), 90 author.clone(), 91 published_at, 92 kind, 93 content.clone(), 94 tags.clone(), 95 )?; 96 RadrootsParsedEvent::from_event_parts(id, author, published_at, kind, content, tags, sig, data) 97 } 98 99 fn parse_farm_anchor(tags: &[Vec<String>]) -> Result<Option<SocialFarmAnchor>, EventParseError> { 100 let Some(value) = first_tag_value(tags, TAG_A) else { 101 return Ok(None); 102 }; 103 let address = parse_address_tag_with_kind(&value, KIND_FARM, TAG_A)?; 104 Ok(Some(SocialFarmAnchor { 105 farm: FarmRef { 106 pubkey: address.pubkey, 107 d_tag: address.d_tag, 108 }, 109 relays: None, 110 })) 111 } 112 113 fn non_empty_vec(values: Vec<String>) -> Option<Vec<String>> { 114 if values.is_empty() { 115 None 116 } else { 117 Some(values) 118 } 119 }