A better Rust ATProto crate
0
fork

Configure Feed

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

1# Jacquard 2 3A suite of Rust crates for the AT Protocol. 4 5[![Crates.io](https://img.shields.io/crates/v/jacquard.svg)](https://crates.io/crates/jacquard) [![Documentation](https://docs.rs/jacquard/badge.svg)](https://docs.rs/jacquard) [![License](https://img.shields.io/crates/l/jacquard.svg)](./LICENSE) 6 7## Goals 8 9- Validated, spec-compliant, easy to work with, and performant baseline types (including typed at:// uris) 10- Batteries-included, but easily replaceable batteries. 11 - Easy to extend with custom lexicons 12- lexicon Value type for working with unknown atproto data (dag-cbor or json) 13- order of magnitude less boilerplate than some existing crates 14 - either the codegen produces code that's easy to work with, or there are good handwritten wrappers 15- didDoc type with helper methods for getting handles, multikey, and PDS endpoint 16- use as much or as little from the crates as you need 17 18 19## Example 20 21Dead simple api client. Logs in, prints the latest 5 posts from your timeline. 22 23```rust 24use clap::Parser; 25use jacquard::CowStr; 26use jacquard::api::app_bsky::feed::get_timeline::GetTimeline; 27use jacquard::api::com_atproto::server::create_session::CreateSession; 28use jacquard::client::{BasicClient, Session}; 29use miette::IntoDiagnostic; 30 31#[derive(Parser, Debug)] 32#[command(author, version, about = "Jacquard - AT Protocol client demo")] 33struct Args { 34 /// Username/handle (e.g., alice.mosphere.at) 35 #[arg(short, long)] 36 username: CowStr<'static>, 37 38 /// PDS URL (e.g., https://bsky.social) 39 #[arg(long, default_value = "https://bsky.social")] 40 pds: CowStr<'static>, 41 42 /// App password 43 #[arg(short, long)] 44 password: CowStr<'static>, 45} 46 47#[tokio::main] 48async fn main() -> miette::Result<()> { 49 let args = Args::parse(); 50 51 // Create HTTP client 52 let base = url::Url::parse(&args.pds).into_diagnostic()?; 53 let client = BasicClient::new(base); 54 55 // Create session 56 let session = Session::from( 57 client 58 .send( 59 CreateSession::new() 60 .identifier(args.username) 61 .password(args.password) 62 .build(), 63 ) 64 .await? 65 .into_output()?, 66 ); 67 68 println!("logged in as {} ({})", session.handle, session.did); 69 client.set_session(session).await.into_diagnostic()?; 70 71 // Fetch timeline 72 println!("\nfetching timeline..."); 73 let timeline = client 74 .send(GetTimeline::new().limit(5).build()) 75 .await? 76 .into_output()?; 77 78 println!("\ntimeline ({} posts):", timeline.feed.len()); 79 for (i, post) in timeline.feed.iter().enumerate() { 80 println!("\n{}. by {}", i + 1, post.post.author.handle); 81 println!( 82 " {}", 83 serde_json::to_string_pretty(&post.post.record).into_diagnostic()? 84 ); 85 } 86 87 Ok(()) 88} 89``` 90 91## Development 92 93This repo uses [Flakes](https://nixos.asia/en/flakes) from the get-go. 94 95```bash 96# Dev shell 97nix develop 98 99# or run via cargo 100nix develop -c cargo run 101 102# build 103nix build 104``` 105 106There's also a [`justfile`](https://just.systems/) for Makefile-esque commands to be run inside of the devShell, and you can generally `cargo ...` or `just ...` whatever just fine if you don't want to use Nix and have the prerequisites installed.