The smokesignal.events web application
0
fork

Configure Feed

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

at main 125 lines 3.3 kB view raw
1use atproto_record::aturi::ATURI; 2use axum::{ 3 extract::{Query, State}, 4 response::{IntoResponse, Json}, 5}; 6use http::StatusCode; 7use serde::{Deserialize, Serialize}; 8use std::str::FromStr; 9 10use crate::http::context::WebContext; 11use crate::storage::event::rsvp_get_by_event_and_did; 12 13#[derive(Debug, Deserialize)] 14pub struct GetRsvpParams { 15 /// AT-URI of the event 16 event: String, 17 /// DID of the identity to get the RSVP for 18 identity: String, 19} 20 21#[derive(Debug, Serialize)] 22pub struct GetRsvpResponse { 23 /// AT-URI of the RSVP record 24 uri: String, 25 /// CID of the RSVP record 26 cid: String, 27 /// The RSVP record 28 record: serde_json::Value, 29} 30 31#[derive(Debug, Serialize)] 32struct GetRsvpError { 33 error: String, 34 message: String, 35} 36 37impl GetRsvpError { 38 fn invalid_request(message: &str) -> Self { 39 Self { 40 error: "InvalidRequest".to_string(), 41 message: message.to_string(), 42 } 43 } 44 45 fn not_found(message: &str) -> Self { 46 Self { 47 error: "NotFound".to_string(), 48 message: message.to_string(), 49 } 50 } 51 52 fn internal_error(message: &str) -> Self { 53 Self { 54 error: "InternalServerError".to_string(), 55 message: message.to_string(), 56 } 57 } 58} 59 60/// XRPC query endpoint for getting an RSVP record. 61/// 62/// This endpoint retrieves an RSVP record for a specific identity and event. 63/// No authentication is required as RSVP data is public. 64pub(crate) async fn handle_xrpc_get_rsvp( 65 State(web_context): State<WebContext>, 66 Query(params): Query<GetRsvpParams>, 67) -> impl IntoResponse { 68 // Validate event AT-URI format 69 if ATURI::from_str(&params.event).is_err() { 70 return ( 71 StatusCode::BAD_REQUEST, 72 Json(GetRsvpError::invalid_request("Invalid event AT-URI format")), 73 ) 74 .into_response(); 75 } 76 77 let identity = match web_context 78 .identity_resolver 79 .resolve(&params.identity) 80 .await 81 { 82 Ok(value) => value, 83 Err(_) => { 84 return ( 85 StatusCode::BAD_REQUEST, 86 Json(GetRsvpError::invalid_request("Invalid identity DID format")), 87 ) 88 .into_response(); 89 } 90 }; 91 92 // Fetch the RSVP 93 let rsvp = match rsvp_get_by_event_and_did(&web_context.pool, &params.event, &identity.id).await 94 { 95 Ok(Some(rsvp)) => rsvp, 96 Ok(None) => { 97 return ( 98 StatusCode::NOT_FOUND, 99 Json(GetRsvpError::not_found("RSVP not found")), 100 ) 101 .into_response(); 102 } 103 Err(err) => { 104 tracing::error!( 105 ?err, 106 event = %params.event, 107 identity = %params.identity, 108 "Failed to fetch RSVP" 109 ); 110 return ( 111 StatusCode::INTERNAL_SERVER_ERROR, 112 Json(GetRsvpError::internal_error("Failed to fetch RSVP")), 113 ) 114 .into_response(); 115 } 116 }; 117 118 let response = GetRsvpResponse { 119 uri: rsvp.aturi, 120 cid: rsvp.cid, 121 record: rsvp.record.0, 122 }; 123 124 (StatusCode::OK, Json(response)).into_response() 125}