lib

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

decode.rs (3495B)


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