Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto
at fix-compose-path 80 lines 2.4 kB view raw
1use axum::{ 2 extract::{Query, State}, 3 http::StatusCode, 4 Json, 5}; 6use chrono::{DateTime, Utc}; 7use serde::{Deserialize, Serialize}; 8use sqlx::FromRow; 9 10use crate::AppState; 11 12// Struct to hold the total user count. 13#[derive(Serialize, Deserialize, Debug, FromRow)] 14pub struct TotalUsers { 15 pub total_users: i64, 16} 17 18// Endpoint to get the total number of users. 19pub async fn get_total_users( 20 State(state): State<AppState>, 21) -> Result<Json<TotalUsers>, (StatusCode, String)> { 22 let total_users_result = 23 sqlx::query_as::<_, TotalUsers>("SELECT COUNT(*) as total_users FROM profiles") 24 .fetch_one(&state.db_pool) 25 .await; 26 27 match total_users_result { 28 Ok(result) => Ok(Json(result)), 29 Err(e) => Err(( 30 StatusCode::INTERNAL_SERVER_ERROR, 31 format!("Database error (total users): {}", e), 32 )), 33 } 34} 35 36// Struct to represent a latest signup. Optional fields are now used. 37#[derive(Serialize, Deserialize, Debug, FromRow)] 38pub struct LatestSignup { 39 pub did: String, 40 pub display_name: Option<String>, // Now optional 41 pub handle: Option<String>, 42 pub created_at: Option<DateTime<Utc>>, // Now optional 43 pub avatar: Option<String>, // Now optional 44 pub banner: Option<String>, // Now optional 45} 46 47const fn default_limit() -> i64 { 48 12 49} 50 51#[derive(Debug, Clone, Deserialize, Serialize)] 52pub struct LatestSignupQueryParams { 53 #[serde(default = "default_limit")] 54 pub limit: i64, 55} 56 57// Endpoint to get the latest signups. 58pub async fn get_latest_signups( 59 State(state): State<AppState>, 60 Query(params): Query<LatestSignupQueryParams>, 61) -> Result<Json<Vec<LatestSignup>>, (StatusCode, String)> { 62 if params.limit < 1 || params.limit > 50 { 63 return Err((StatusCode::BAD_REQUEST, "Invalid limit".to_string())); 64 } 65 66 let latest_signups_result = sqlx::query_as::<_, LatestSignup>( 67 "SELECT did, display_name, handle, created_at, avatar, banner FROM profiles ORDER BY created_at DESC LIMIT $1", 68 ) 69 .bind(params.limit) 70 .fetch_all(&state.db_pool) 71 .await; 72 73 match latest_signups_result { 74 Ok(signups) => Ok(Json(signups)), 75 Err(e) => Err(( 76 StatusCode::INTERNAL_SERVER_ERROR, 77 format!("Database error (latest signups): {}", e), 78 )), 79 } 80}