Constellation, Spacedust, Slingshot, UFOs: atproto crates and services for microcosm
75
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 163 lines 5.4 kB view raw
1use tinyjson::JsonValue; 2 3use crate::{parse_any_link, CollectedLink}; 4 5pub fn walk_record(path: &str, v: &JsonValue, found: &mut Vec<CollectedLink>) { 6 match v { 7 JsonValue::Object(o) => { 8 for (key, child) in o { 9 walk_record(&format!("{path}.{key}"), child, found) 10 } 11 } 12 JsonValue::Array(a) => { 13 for child in a { 14 let child_p = match child { 15 JsonValue::Object(o) => { 16 if let Some(JsonValue::String(t)) = o.get("$type") { 17 format!("{path}[{t}]") 18 } else { 19 format!("{path}[]") 20 } 21 } 22 _ => format!("{path}[]"), 23 }; 24 walk_record(&child_p, child, found) 25 } 26 } 27 JsonValue::String(s) => { 28 if let Some(link) = parse_any_link(s) { 29 found.push(CollectedLink { 30 path: path.to_string(), 31 target: link, 32 }); 33 } 34 } 35 _ => {} 36 } 37} 38 39pub fn collect_links(v: &JsonValue) -> Vec<CollectedLink> { 40 let mut found = vec![]; 41 walk_record("", v, &mut found); 42 found 43} 44 45#[cfg(test)] 46mod tests { 47 use super::*; 48 use crate::Link; 49 50 fn l(path: &str, target: Link) -> CollectedLink { 51 CollectedLink { 52 path: path.into(), 53 target, 54 } 55 } 56 57 #[test] 58 fn test_collect_links() { 59 let rec = r#"{"a": "https://example.com", "b": "not a link"}"#; 60 let json = collect_links(&rec.parse().unwrap()); 61 assert_eq!(json, vec![l(".a", Link::Uri("https://example.com".into()))]); 62 } 63 64 #[test] 65 fn test_bsky_feed_post_record_reply() { 66 let rec = r#"{ 67 "$type": "app.bsky.feed.post", 68 "createdAt": "2025-01-08T20:52:43.041Z", 69 "langs": [ 70 "en" 71 ], 72 "reply": { 73 "parent": { 74 "cid": "bafyreifk3bwnmulk37ezrarg4ouheqnhgucypynftqafl4limssogvzk6i", 75 "uri": "at://did:plc:b3rzzkblqsxhr3dgcueymkqe/app.bsky.feed.post/3lf6yc4drhk2f" 76 }, 77 "root": { 78 "cid": "bafyreifk3bwnmulk37ezrarg4ouheqnhgucypynftqafl4limssogvzk6i", 79 "uri": "at://did:plc:b3rzzkblqsxhr3dgcueymkqe/app.bsky.feed.post/3lf6yc4drhk2f" 80 } 81 }, 82 "text": "Yup!" 83 }"#; 84 let mut json = collect_links(&rec.parse().unwrap()); 85 json.sort_by_key(|c| (c.path.clone(), c.target.clone())); 86 assert_eq!( 87 json, 88 vec![ 89 l( 90 ".reply.parent.uri", 91 Link::AtUri( 92 "at://did:plc:b3rzzkblqsxhr3dgcueymkqe/app.bsky.feed.post/3lf6yc4drhk2f" 93 .into() 94 ) 95 ), 96 l( 97 ".reply.root.uri", 98 Link::AtUri( 99 "at://did:plc:b3rzzkblqsxhr3dgcueymkqe/app.bsky.feed.post/3lf6yc4drhk2f" 100 .into() 101 ) 102 ), 103 ] 104 ) 105 } 106 107 #[test] 108 fn test_bsky_feed_post_record_embed() { 109 let rec = r#"{ 110 "$type": "app.bsky.feed.post", 111 "createdAt": "2025-01-08T20:52:39.539Z", 112 "embed": { 113 "$type": "app.bsky.embed.external", 114 "external": { 115 "description": "YouTube video by More Perfect Union", 116 "thumb": { 117 "$type": "blob", 118 "ref": { 119 "$link": "bafkreifxuvkbqksq5usi4cryex37o4absjexuouvgenlb62ojsx443b2tm" 120 }, 121 "mimeType": "image/jpeg", 122 "size": 477460 123 }, 124 "title": "Corporations & Wealthy Elites Are Coopting Our Government. Who Can Stop Them?", 125 "uri": "https://youtu.be/oKXm4szEP1Q?si=_0n_uPu4qNKokMnq" 126 } 127 }, 128 "facets": [ 129 { 130 "features": [ 131 { 132 "$type": "app.bsky.richtext.facet#link", 133 "uri": "https://youtu.be/oKXm4szEP1Q?si=_0n_uPu4qNKokMnq" 134 } 135 ], 136 "index": { 137 "byteEnd": 24, 138 "byteStart": 0 139 } 140 } 141 ], 142 "langs": [ 143 "en" 144 ], 145 "text": "youtu.be/oKXm4szEP1Q?..." 146 }"#; 147 let mut json = collect_links(&rec.parse().unwrap()); 148 json.sort_by_key(|c| (c.path.clone(), c.target.clone())); 149 assert_eq!( 150 json, 151 vec![ 152 l( 153 ".embed.external.uri", 154 Link::Uri("https://youtu.be/oKXm4szEP1Q?si=_0n_uPu4qNKokMnq".into()), 155 ), 156 l( 157 ".facets[].features[app.bsky.richtext.facet#link].uri", 158 Link::Uri("https://youtu.be/oKXm4szEP1Q?si=_0n_uPu4qNKokMnq".into()), 159 ), 160 ] 161 ) 162 } 163}