Add user stats route

This commit is contained in:
2026-03-21 22:01:58 +01:00
parent f19e443eb2
commit be438aa1af
4 changed files with 101 additions and 12 deletions

View File

@@ -1,13 +1,20 @@
use std::i64;
use anyhow::Result;
use serde::Serialize;
use sqlx::{Row, SqlitePool};
use std::i64;
#[derive(Clone)]
pub struct Database {
pool: SqlitePool,
}
#[derive(Serialize)]
pub struct UserStats {
pub name: String,
pub rating_count: i64,
pub average_rating: f64,
}
impl Database {
pub async fn new() -> Result<Self> {
let pool = SqlitePool::connect("sqlite://ratings.db?mode=rwc").await?;
@@ -218,7 +225,7 @@ impl Database {
Ok(())
}
pub async fn get_user_most_ratings(&self) -> Result<()> {
pub async fn get_user_most_ratings(&self) -> Result<Vec<UserStats>> {
let mut conn = self.pool.acquire().await?;
let records = sqlx::query(
@@ -233,16 +240,16 @@ impl Database {
.fetch_all(&mut *conn)
.await?;
//let id = record.try_get("id")?;
// Map the database records into our new struct
let mut stats = Vec::new();
for r in records {
let name: &str = r.try_get("name")?;
let count: i64 = r.try_get("c")?;
let avg: f64 = r.try_get("avg(rating)")?;
println!("Name: {name}, Ratings: {count}, Average: {avg}");
stats.push(UserStats {
name: r.try_get("name")?,
rating_count: r.try_get("c")?,
average_rating: r.try_get("avg(rating)")?,
});
}
Ok(())
Ok(stats)
}
}

View File

@@ -8,9 +8,10 @@ use axum::{
http::StatusCode,
response::{IntoResponse, Response},
routing::get,
Router,
Json, Router,
};
use tokio::sync::watch::Sender;
use tower_http::services::ServeDir;
use crate::database::Database;
@@ -31,6 +32,8 @@ pub async fn http_serve(database: &Database, mpris_producer: Sender<(String, Str
};
let app = Router::new()
.fallback_service(ServeDir::new("static"))
.route("/stats", get(get_stats))
.route("/", get(root))
.route("/rating/:rating", get(cache_rating_only))
.route("/userid/:user_id", get(add_userid))
@@ -127,3 +130,17 @@ async fn add_userid_by_card(
}
}
}
async fn get_stats(State(shared): State<SharedState>) -> Response {
match shared.database.get_user_most_ratings().await {
Ok(stats) => {
// axum::Json automatically serializes the Vec<UserStats> into a JSON array
// and sets the correct "Content-Type: application/json" headers.
(StatusCode::OK, Json(stats)).into_response()
}
Err(e) => {
eprintln!("Database error: {e}");
(StatusCode::INTERNAL_SERVER_ERROR, "Failed to fetch stats").into_response()
}
}
}