lib

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

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 }