A better Rust ATProto crate
103
fork

Configure Feed

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

pds param on credential session login, logic to handle emails, language tag deserialization bugfix.

Orual 0f8930b9 9cb1a46e

+21 -4
+8 -2
crates/jacquard-common/src/types/language.rs
··· 1 + use langtag::InvalidLangTag; 1 2 use serde::{Deserialize, Deserializer, Serialize, de::Error}; 2 3 use smol_str::{SmolStr, ToSmolStr}; 3 4 use std::fmt; ··· 36 37 Ok(Language(SmolStr::new_static(tag.as_str()))) 37 38 } 38 39 40 + fn new_owned(lang: SmolStr) -> Result<Self, SmolStr> { 41 + let tag = langtag::LangTag::new(&lang).map_err(|e| e.to_smolstr())?; 42 + Ok(Language(SmolStr::new(tag.as_str()))) 43 + } 44 + 39 45 /// Infallible constructor for when you *know* the string is a valid IETF language tag. 40 46 /// Will panic on invalid tag. If you're manually decoding atproto records 41 47 /// or API values you know are valid (rather than using serde), this is the one to use. ··· 75 81 where 76 82 D: Deserializer<'de>, 77 83 { 78 - let value: &str = Deserialize::deserialize(deserializer)?; 79 - Self::new(value).map_err(D::Error::custom) 84 + let value = Deserialize::deserialize(deserializer)?; 85 + Self::new_owned(value).map_err(D::Error::custom) 80 86 } 81 87 } 82 88
+2 -1
crates/jacquard/src/client.rs
··· 452 452 identifier: CowStr<'_>, 453 453 password: CowStr<'_>, 454 454 session_id: Option<CowStr<'_>>, 455 + pds: Option<Url>, 455 456 ) -> ClientResult<(Self, AtpSession)> { 456 457 let session = MemoryCredentialSession::unauthenticated(); 457 458 let auth = session 458 - .login(identifier, password, session_id, None, None) 459 + .login(identifier, password, session_id, None, None, pds) 459 460 .await?; 460 461 Ok((session, auth)) 461 462 }
+10 -1
crates/jacquard/src/client/credential_session.rs
··· 204 204 session_id: Option<CowStr<'_>>, 205 205 allow_takendown: Option<bool>, 206 206 auth_factor_token: Option<CowStr<'_>>, 207 + pds: Option<Url>, 207 208 ) -> std::result::Result<AtpSession, ClientError> 208 209 where 209 210 S: Any + 'static, ··· 213 214 tracing::info_span!("credential_session_login", identifier = %identifier).entered(); 214 215 215 216 // Resolve PDS base 216 - let pds = if identifier.as_ref().starts_with("http://") 217 + let pds = if let Some(pds) = pds { 218 + pds 219 + } else if identifier.as_ref().starts_with("http://") 217 220 || identifier.as_ref().starts_with("https://") 218 221 { 219 222 Url::parse(identifier.as_ref()).map_err(|e: url::ParseError| { ··· 231 234 resp.into_owned()?.pds_endpoint().ok_or_else(|| { 232 235 ClientError::invalid_request("missing PDS endpoint") 233 236 .with_help("DID document must include a PDS service endpoint") 237 + })? 238 + } else if identifier.as_ref().contains("@") && !identifier.as_ref().starts_with("@") { 239 + // we're going to assume its an email 240 + pds.ok_or_else(|| { 241 + ClientError::invalid_request("missing PDS endpoint") 242 + .with_help("When logging in with email, we need your PDS") 234 243 })? 235 244 } else { 236 245 // treat as handle
+1
crates/jacquard/tests/credential_session.rs
··· 179 179 Some(jacquard::CowStr::from("session")), 180 180 None, 181 181 None, 182 + None, 182 183 ) 183 184 .await 184 185 .expect("login ok");