Your music, beautifully tracked. All yours. (coming soon)
teal.fm
teal-fm
atproto
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}