lib

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

decode.rs (3584B)


      1 #![cfg(feature = "serde_json")]
      2 
      3 #[cfg(not(feature = "std"))]
      4 use alloc::{
      5     string::{String, ToString},
      6     vec::Vec,
      7 };
      8 
      9 use super::RadrootsProfileData;
     10 use radroots_events::{
     11     RadrootsNostrEvent,
     12     kinds::KIND_PROFILE,
     13     profile::{
     14         RADROOTS_PROFILE_TYPE_TAG_KEY, RadrootsProfile, RadrootsProfileType,
     15         radroots_profile_type_from_tag_value,
     16     },
     17 };
     18 
     19 use crate::error::EventParseError;
     20 use crate::parsed::{RadrootsParsedData, RadrootsParsedEvent};
     21 use serde_json::Value;
     22 
     23 const PROFILE_KIND: u32 = KIND_PROFILE;
     24 
     25 fn parse_optional_string(value: &Value, key: &'static str) -> Option<String> {
     26     value
     27         .get(key)
     28         .and_then(|v| v.as_str())
     29         .map(|s| s.to_string())
     30 }
     31 
     32 fn parse_bot(value: &Value) -> Option<String> {
     33     match value.get("bot") {
     34         Some(v) if v.is_string() => v.as_str().map(|s| s.to_string()),
     35         Some(v) if v.is_boolean() => v.as_bool().map(|b| b.to_string()),
     36         _ => None,
     37     }
     38 }
     39 
     40 fn profile_type_from_tags(tags: &[Vec<String>]) -> Option<RadrootsProfileType> {
     41     tags.iter()
     42         .filter(|tag| tag.first().map(|v| v.as_str()) == Some(RADROOTS_PROFILE_TYPE_TAG_KEY))
     43         .filter_map(|tag| tag.get(1))
     44         .find_map(|value| radroots_profile_type_from_tag_value(value))
     45 }
     46 
     47 pub fn profile_from_content(content: &str) -> Result<RadrootsProfile, EventParseError> {
     48     let value: Value =
     49         serde_json::from_str(content).map_err(|_| EventParseError::InvalidJson("content"))?;
     50     let obj = value
     51         .as_object()
     52         .ok_or(EventParseError::InvalidJson("content"))?;
     53     let name = obj
     54         .get("name")
     55         .and_then(|v| v.as_str())
     56         .ok_or(EventParseError::InvalidJson("name"))?;
     57 
     58     Ok(RadrootsProfile {
     59         name: name.to_string(),
     60         display_name: parse_optional_string(&value, "display_name"),
     61         nip05: parse_optional_string(&value, "nip05"),
     62         about: parse_optional_string(&value, "about"),
     63         website: parse_optional_string(&value, "website"),
     64         picture: parse_optional_string(&value, "picture"),
     65         banner: parse_optional_string(&value, "banner"),
     66         lud06: parse_optional_string(&value, "lud06"),
     67         lud16: parse_optional_string(&value, "lud16"),
     68         bot: parse_bot(&value),
     69     })
     70 }
     71 
     72 pub fn data_from_event(
     73     id: String,
     74     author: String,
     75     published_at: u32,
     76     kind: u32,
     77     content: String,
     78     tags: Vec<Vec<String>>,
     79 ) -> Result<RadrootsParsedData<RadrootsProfileData>, EventParseError> {
     80     if kind != PROFILE_KIND {
     81         return Err(EventParseError::InvalidKind {
     82             expected: "0",
     83             got: kind,
     84         });
     85     }
     86     let profile = profile_from_content(&content)?;
     87     let profile_type = profile_type_from_tags(&tags);
     88     Ok(RadrootsParsedData::new(
     89         id,
     90         author,
     91         published_at,
     92         kind,
     93         RadrootsProfileData {
     94             profile_type,
     95             profile,
     96         },
     97     ))
     98 }
     99 
    100 pub fn parsed_from_event(
    101     id: String,
    102     author: String,
    103     published_at: u32,
    104     kind: u32,
    105     content: String,
    106     tags: Vec<Vec<String>>,
    107     sig: String,
    108 ) -> Result<RadrootsParsedEvent<RadrootsProfileData>, EventParseError> {
    109     let data = data_from_event(
    110         id.clone(),
    111         author.clone(),
    112         published_at,
    113         kind,
    114         content.clone(),
    115         tags.clone(),
    116     )?;
    117     Ok(RadrootsParsedEvent {
    118         event: RadrootsNostrEvent {
    119             id,
    120             author,
    121             created_at: published_at,
    122             kind,
    123             content,
    124             tags,
    125             sig,
    126         },
    127         data,
    128     })
    129 }