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

feat(parakeet): really incomplete com.atproto.repo.getRecord impl

+79
+2
parakeet/src/xrpc/com_atproto/mod.rs
··· 2 2 use axum::Router; 3 3 4 4 mod identity; 5 + mod repo; 5 6 6 7 #[rustfmt::skip] 7 8 pub fn routes() -> Router<crate::GlobalState> { 8 9 Router::new() 9 10 .route("/com.atproto.identity.resolveHandle", get(identity::resolve_handle)) 11 + .route("/com.atproto.repo.getRecord", get(repo::get_record)) 10 12 }
+77
parakeet/src/xrpc/com_atproto/repo.rs
··· 1 + use crate::xrpc::check_actor_status; 2 + use crate::xrpc::error::{Error, XrpcResult}; 3 + use crate::xrpc::extract::AtpAuth; 4 + use crate::GlobalState; 5 + use axum::extract::{Query, State}; 6 + use axum::Json; 7 + use diesel::prelude::*; 8 + use diesel_async::RunQueryDsl; 9 + use parakeet_db::schema; 10 + use serde::{Deserialize, Serialize}; 11 + use serde_json::Value; 12 + 13 + #[derive(Debug, Deserialize)] 14 + pub struct GetRecordQuery { 15 + pub repo: String, 16 + pub collection: String, 17 + pub rkey: String, 18 + } 19 + 20 + #[derive(Debug, Serialize)] 21 + pub struct GetRecordRes { 22 + pub uri: String, 23 + pub cid: String, 24 + pub value: Value, 25 + } 26 + 27 + pub async fn get_record( 28 + State(state): State<GlobalState>, 29 + _maybe_auth: Option<AtpAuth>, 30 + Query(query): Query<GetRecordQuery>, 31 + ) -> XrpcResult<Json<GetRecordRes>> { 32 + let mut conn = state.pool.get().await?; 33 + 34 + check_actor_status(&mut conn, &query.repo).await?; 35 + 36 + let at_uri = format!("at://{}/{}/{}", &query.repo, &query.collection, &query.rkey); 37 + 38 + let (cid, value) = match query.collection.as_str() { 39 + "app.bsky.feed.generator" => { 40 + // we don't store the full data so this returns partial 41 + let (cid, service_did) = schema::feedgens::table 42 + .select((schema::feedgens::cid, schema::feedgens::service_did)) 43 + .find(&at_uri) 44 + .get_result::<(String, String)>(&mut conn) 45 + .await?; 46 + 47 + ( 48 + cid, 49 + serde_json::json!({ 50 + "$type": "app.bsky.feed.generator", 51 + "did": service_did, 52 + }), 53 + ) 54 + } 55 + "app.bsky.feed.post" => { 56 + schema::posts::table 57 + .select((schema::posts::cid, schema::posts::record)) 58 + .find(&at_uri) 59 + .get_result::<(String, Value)>(&mut conn) 60 + .await? 61 + } 62 + "app.bsky.graph.starterpack" => { 63 + schema::starterpacks::table 64 + .select((schema::starterpacks::cid, schema::starterpacks::record)) 65 + .find(&at_uri) 66 + .get_result::<(String, Value)>(&mut conn) 67 + .await? 68 + } 69 + _ => return Err(Error::invalid_request(None)), 70 + }; 71 + 72 + Ok(Json(GetRecordRes { 73 + uri: at_uri, 74 + cid, 75 + value, 76 + })) 77 + }