Parakeet is a Rust-based Bluesky AppServer aiming to implement most of the functionality required to support the Bluesky client
appview atproto bluesky rust appserver
66
fork

Configure Feed

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

lexgen process flow

Mia 1389d56e 4ec9513d

+75 -1
+21
Cargo.lock
··· 160 160 "eyre", 161 161 "serde", 162 162 "serde_json", 163 + "thiserror", 163 164 "walkdir", 164 165 ] 165 166 ··· 243 244 "proc-macro2", 244 245 "quote", 245 246 "unicode-ident", 247 + ] 248 + 249 + [[package]] 250 + name = "thiserror" 251 + version = "2.0.11" 252 + source = "registry+https://github.com/rust-lang/crates.io-index" 253 + checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 254 + dependencies = [ 255 + "thiserror-impl", 256 + ] 257 + 258 + [[package]] 259 + name = "thiserror-impl" 260 + version = "2.0.11" 261 + source = "registry+https://github.com/rust-lang/crates.io-index" 262 + checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 263 + dependencies = [ 264 + "proc-macro2", 265 + "quote", 266 + "syn", 246 267 ] 247 268 248 269 [[package]]
+1
parakeet-lexgen/Cargo.toml
··· 8 8 eyre = "0.6.12" 9 9 serde = { version = "1.0.217", features = ["derive"] } 10 10 serde_json = "1.0.136" 11 + thiserror = "2.0.11" 11 12 walkdir = "2.5.0"
+53 -1
parakeet-lexgen/src/main.rs
··· 1 1 use clap::Parser; 2 + use std::collections::BTreeMap; 2 3 use walkdir::WalkDir; 3 4 4 5 mod types; ··· 14 15 no_validate: bool, 15 16 } 16 17 18 + #[derive(Debug, thiserror::Error)] 19 + enum Error { 20 + #[error("{0}")] 21 + Serde(#[from] serde_json::Error), 22 + #[error("{0}")] 23 + Io(#[from] std::io::Error), 24 + } 25 + 17 26 fn main() -> eyre::Result<()> { 18 27 let args = Cli::parse(); 19 28 ··· 31 40 true => Some(path.to_path_buf()), 32 41 false => None, 33 42 } 34 - }).collect::<Vec<_>>(); 43 + }) 44 + .collect::<Vec<_>>(); 45 + 46 + let (parsed, errors) = lexicon_files 47 + .into_iter() 48 + .map(|path| { 49 + let filename = path.display().to_string(); 50 + 51 + let file = 52 + std::fs::File::open(path).map_err(|err| (filename.clone(), Error::from(err)))?; 53 + 54 + let res = serde_json::from_reader::<_, types::Lexicon>(file) 55 + .map_err(|err| (filename, Error::from(err)))?; 56 + 57 + Ok(res) 58 + }) 59 + .map(|v| match v { 60 + Ok(v) => (Some(v), None), 61 + Err(e) => (None, Some(e)), 62 + }) 63 + .unzip::<_, _, Vec<_>, Vec<_>>(); 64 + 65 + // report the errors 66 + for error in errors { 67 + if let Some((filename, error)) = error { 68 + eprintln!("Lexicon {filename} parse failed: {error}"); 69 + } 70 + } 71 + 72 + // pull all the valid lexicon files into a big map so we can run validation 73 + let parsed = parsed 74 + .into_iter() 75 + .filter_map(|maybe_lexicon| match maybe_lexicon { 76 + Some(lexicon) => Some((lexicon.id.clone(), lexicon)), 77 + None => None, 78 + }) 79 + .collect::<BTreeMap<_, _>>(); 80 + 81 + if !args.no_validate { 82 + let failed = validate::validate(&parsed); 83 + for (fail_nsid, fail_err) in failed { 84 + eprintln!("Lexicon {fail_nsid} failed validation: {fail_err:?}"); 85 + } 86 + } 35 87 36 88 Ok(()) 37 89 }