lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

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 }