lib

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

event_ref.rs (5788B)


      1 #[cfg(not(feature = "std"))]
      2 use alloc::{
      3     string::{String, ToString},
      4     vec,
      5     vec::Vec,
      6 };
      7 
      8 use radroots_event::{
      9     id::{DTag, EventId, RelayUrl},
     10     tag::EventRef,
     11 };
     12 use radroots_identity::PublicKey;
     13 
     14 use crate::error::EventParseError;
     15 
     16 pub fn build_event_ref_tag(tag: &str, event: &EventRef) -> Vec<String> {
     17     let relays_len = event.relays.as_ref().map(|r| r.len()).unwrap_or(0);
     18     let mut out = Vec::with_capacity(5 + relays_len);
     19     out.push(tag.to_string());
     20     out.push(event.id.clone());
     21     out.push(event.author.to_hex());
     22     out.push(event.kind.to_string());
     23     out.push(event.d_tag.clone().unwrap_or_default());
     24     if let Some(relays) = &event.relays {
     25         out.extend(relays.iter().cloned());
     26     }
     27     out
     28 }
     29 
     30 pub fn parse_event_ref_tag(
     31     tag: &[String],
     32     tag_name: &'static str,
     33 ) -> Result<EventRef, EventParseError> {
     34     if tag.first().map(|s| s.as_str()) != Some(tag_name) {
     35         return Err(EventParseError::InvalidTag(tag_name));
     36     }
     37     if tag.len() < 5 {
     38         return Err(EventParseError::InvalidTag(tag_name));
     39     }
     40     let id = &tag[1];
     41     EventId::parse(id).map_err(|_| EventParseError::InvalidTag(tag_name))?;
     42     let author = &tag[2];
     43     let author = PublicKey::from_hex(author).map_err(|_| EventParseError::InvalidTag(tag_name))?;
     44     let kind_s = &tag[3];
     45     let kind: u32 = kind_s
     46         .parse()
     47         .map_err(|e| EventParseError::InvalidNumber(tag_name, e))?;
     48 
     49     let d_tag_value = &tag[4];
     50     let d_tag = if d_tag_value.is_empty() {
     51         None
     52     } else {
     53         if RelayUrl::parse(d_tag_value).is_ok() {
     54             return Err(EventParseError::InvalidTag(tag_name));
     55         }
     56         DTag::parse(d_tag_value).map_err(|_| EventParseError::InvalidTag(tag_name))?;
     57         Some(d_tag_value.clone())
     58     };
     59 
     60     let relays = if tag.len() > 5 {
     61         for relay in &tag[5..] {
     62             RelayUrl::parse(relay).map_err(|_| EventParseError::InvalidTag(tag_name))?;
     63         }
     64         Some(tag[5..].to_vec())
     65     } else {
     66         None
     67     };
     68 
     69     Ok(EventRef {
     70         id: id.clone(),
     71         author,
     72         kind,
     73         d_tag,
     74         relays,
     75     })
     76 }
     77 
     78 pub fn find_event_ref_tag<'a>(
     79     tags: &'a [Vec<String>],
     80     tag_name: &'static str,
     81 ) -> Option<&'a Vec<String>> {
     82     tags.iter()
     83         .find(|t| t.first().map(|s| s.as_str()) == Some(tag_name))
     84 }
     85 
     86 pub fn push_nip10_ref_tags(
     87     tags: &mut Vec<Vec<String>>,
     88     event: &EventRef,
     89     tag_e: &'static str,
     90     tag_p: &'static str,
     91     tag_k: &'static str,
     92     tag_a: &'static str,
     93 ) {
     94     let relays_len = event.relays.as_ref().map(|r| r.len()).unwrap_or(0);
     95     let kind_str = event.kind.to_string();
     96 
     97     let mut e_tag = Vec::with_capacity(2 + relays_len);
     98     e_tag.push(tag_e.to_string());
     99     e_tag.push(event.id.clone());
    100     if let Some(relays) = &event.relays {
    101         e_tag.extend(relays.iter().cloned());
    102     }
    103     tags.push(e_tag);
    104 
    105     let author = event.author.to_hex();
    106     let p_tag = vec![tag_p.to_string(), author.clone()];
    107     tags.push(p_tag);
    108 
    109     let k_tag = vec![tag_k.to_string(), kind_str.clone()];
    110     tags.push(k_tag);
    111 
    112     if let Some(d_tag) = event.d_tag.as_deref().filter(|v| !v.is_empty()) {
    113         let mut addr = String::with_capacity(kind_str.len() + author.len() + d_tag.len() + 2);
    114         addr.push_str(&kind_str);
    115         addr.push(':');
    116         addr.push_str(&author);
    117         addr.push(':');
    118         addr.push_str(d_tag);
    119 
    120         let mut a_tag = Vec::with_capacity(2 + relays_len);
    121         a_tag.push(tag_a.to_string());
    122         a_tag.push(addr);
    123         if let Some(relays) = &event.relays {
    124             a_tag.extend(relays.iter().cloned());
    125         }
    126         tags.push(a_tag);
    127     }
    128 }
    129 
    130 pub fn parse_nip10_ref_tags(
    131     tags: &[Vec<String>],
    132     tag_e: &'static str,
    133     tag_p: &'static str,
    134     tag_k: &'static str,
    135     tag_a: &'static str,
    136 ) -> Result<EventRef, EventParseError> {
    137     let e_tag = find_event_ref_tag(tags, tag_e).ok_or(EventParseError::MissingTag(tag_e))?;
    138     let id = e_tag.get(1).ok_or(EventParseError::InvalidTag(tag_e))?;
    139     if id.trim().is_empty() {
    140         return Err(EventParseError::InvalidTag(tag_e));
    141     }
    142     let relays = if e_tag.len() > 2 {
    143         Some(e_tag[2..].to_vec())
    144     } else {
    145         None
    146     };
    147 
    148     let p_tag = find_event_ref_tag(tags, tag_p).ok_or(EventParseError::MissingTag(tag_p))?;
    149     let author = p_tag.get(1).ok_or(EventParseError::InvalidTag(tag_p))?;
    150     let author = PublicKey::from_hex(author).map_err(|_| EventParseError::InvalidTag(tag_p))?;
    151     let author_hex = author.to_hex();
    152 
    153     let k_tag = find_event_ref_tag(tags, tag_k).ok_or(EventParseError::MissingTag(tag_k))?;
    154     let kind_key = k_tag.get(1).ok_or(EventParseError::InvalidTag(tag_k))?;
    155     let kind: u32 = kind_key
    156         .parse()
    157         .map_err(|e| EventParseError::InvalidNumber(tag_k, e))?;
    158 
    159     let mut d_tag: Option<String> = None;
    160     let mut addr_relays: Option<Vec<String>> = None;
    161     for tag in tags
    162         .iter()
    163         .filter(|t| t.first().map(|s| s.as_str()) == Some(tag_a))
    164     {
    165         let value = match tag.get(1) {
    166             Some(v) => v,
    167             None => continue,
    168         };
    169         let mut parts = value.splitn(3, ':');
    170         let kind_part = parts.next();
    171         let author_part = parts.next();
    172         let d_part = parts.next();
    173         if kind_part != Some(kind_key.as_str()) || author_part != Some(author_hex.as_str()) {
    174             continue;
    175         }
    176         if let Some(d) = d_part
    177             && !d.is_empty()
    178         {
    179             d_tag = Some(d.to_string());
    180         }
    181         if tag.len() > 2 {
    182             addr_relays = Some(tag[2..].to_vec());
    183         }
    184         break;
    185     }
    186 
    187     let relays = relays.or(addr_relays);
    188 
    189     Ok(EventRef {
    190         id: id.clone(),
    191         author,
    192         kind,
    193         d_tag,
    194         relays,
    195     })
    196 }