Something went wrong. Try again.
Rust AppView - highly experimental! forked from parakeet.at/parakeet
Something went wrong. Try again.
Rust
at experiments
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117use jacquard_api::app_bsky::richtext::facet::{Facet as FacetMain, FacetFeaturesItem};use jacquard_common::types::blob::Blob;use jacquard_api::com_atproto::repo::strong_ref::StrongRef;use serde::{Deserialize as _, Deserializer};
// see https://deer.social/profile/did:plc:63y3oh7iakdueqhlj6trojbq/post/3ltuv4skhqs2hpub fn safe_string<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<String>, D::Error> { let str = Option::<String>::deserialize(deserializer)?;
Ok(str.map(|s| s.replace('\u{0000}', "")))}
pub fn safe_string_required<'de, D: Deserializer<'de>>(deserializer: D) -> Result<String, D::Error> { let str = String::deserialize(deserializer)?; Ok(str.replace('\u{0000}', ""))}
pub fn strip_mime_params(mime_type: &str) -> String { // Strip any parameters from the MIME type (e.g., "image/jpeg; quality=90" -> "image/jpeg") mime_type.split(';').next().unwrap_or(mime_type).trim().to_string()}
#[expect(clippy::single_option_map, reason = "Option::map() is clearer than and_then() for simple transformations")]pub fn blob_ref(blob: Option<&Blob>) -> Option<String> { blob.map(|blob| blob.cid().to_string())}
/// Convert a Blob to CID bytes (32-byte digest) for database storagepub fn blob_to_cid_bytes(blob: Option<&Blob>) -> Option<Vec<u8>> { blob.and_then(|blob| { parakeet_db::utils::cid::blob_to_cid_bytes(Some(blob)) })}
pub fn strongref_to_parts(strongref: Option<&StrongRef>) -> (Option<String>, Option<String>) { parakeet_db::utils::cid::strongref_to_parts(strongref)}
/// Convert a StrongRef to (URI, CID digest bytes) for pending linkagepub fn strongref_to_parts_with_digest( strongref: Option<&StrongRef>,) -> (Option<String>, Option<Vec<u8>>) { parakeet_db::utils::cid::strongref_to_parts_with_digest(strongref)}
pub fn at_uri_is_by(uri: &str, did: &str) -> bool { let split_aturi = uri.rsplitn(4, '/').collect::<Vec<_>>();
did == split_aturi[2]}
/// Extract the DID from an AT URI////// AT URIs have the format: `at://{did}/{collection}/{rkey}`/// This function extracts the DID component.pub fn extract_did_from_uri(uri: &str) -> Option<&str> { // AT URI format: at://{did}/{collection}/{rkey} // Split from the right: [rkey, collection, did, "at:/"] let split_aturi = uri.rsplitn(4, '/').collect::<Vec<_>>();
// Check that we have all 4 parts and it starts with "at:" if split_aturi.len() == 4 && split_aturi[3].starts_with("at:") { Some(split_aturi[2]) } else { None }}
pub fn extract_mentions_and_tags(from: &[FacetMain]) -> (Vec<String>, Vec<String>) { let (mentions, tags) = from .iter() .flat_map(|v| { v.features.iter().filter_map(|feature| { match feature { FacetFeaturesItem::Mention(mention) => Some((Some(mention.did.to_string()), None)), FacetFeaturesItem::Tag(tag) => Some((None, Some(tag.tag.to_string()))), _ => None, } }) }) .unzip::<_, _, Vec<_>, Vec<_>>();
let mentions = mentions.into_iter().flatten().collect(); let tags = tags.into_iter().flatten().collect();
(mentions, tags)}
pub fn merge_tags<T>(t1: Option<Vec<T>>, t2: Option<Vec<T>>) -> Vec<T> { match (t1, t2) { (Some(t1), None) => t1, (None, Some(t2)) => t2, (Some(mut t1), Some(t2)) => { t1.extend(t2); t1 } _ => Vec::default(), }}
pub fn deserialize_optional_blob<'de, D>(deserializer: D) -> Result<Option<Blob<'static>>, D::Error>where D: Deserializer<'de>,{ use jacquard_common::IntoStatic; let opt: Option<Blob<'_>> = Option::deserialize(deserializer)?; Ok(opt.map(|b| b.into_static()))}
pub fn deserialize_optional_strongref<'de, D>(deserializer: D) -> Result<Option<StrongRef<'static>>, D::Error>where D: Deserializer<'de>,{ use jacquard_common::IntoStatic; let opt: Option<StrongRef<'_>> = Option::deserialize(deserializer)?; Ok(opt.map(|s| s.into_static()))}