51 lines
1.3 KiB
Rust
51 lines
1.3 KiB
Rust
// {{{ Imports
|
|
use crate::context::AppContext;
|
|
use crate::error::AppError;
|
|
use anyhow::anyhow;
|
|
use axum::{extract::State, http::StatusCode, Json};
|
|
use chrono::{TimeDelta, Utc};
|
|
use shimmeringmoon::arcaea::play::{Play, PlayWithDetails};
|
|
// }}}
|
|
|
|
pub async fn get_recent_play(
|
|
State(state): State<AppContext>,
|
|
) -> Result<Json<PlayWithDetails>, AppError> {
|
|
let after = Utc::now()
|
|
.checked_sub_signed(TimeDelta::minutes(30))
|
|
.unwrap()
|
|
.naive_utc();
|
|
|
|
let (play, song, chart) = state
|
|
.ctx
|
|
.db
|
|
.get()?
|
|
.prepare_cached(
|
|
"
|
|
SELECT
|
|
p.id, p.chart_id, p.user_id, p.created_at,
|
|
p.max_recall, p.far_notes, s.score
|
|
FROM plays p
|
|
JOIN scores s ON s.play_id = p.id
|
|
WHERE s.scoring_system='standard'
|
|
AND p.user_id=?
|
|
AND p.created_at>=?
|
|
ORDER BY p.created_at DESC
|
|
LIMIT 1
|
|
",
|
|
)?
|
|
.query_and_then((2, after), |row| -> Result<_, AppError> {
|
|
let (song, chart) = state.ctx.song_cache.lookup_chart(row.get("chart_id")?)?;
|
|
let play = Play::from_sql(chart, row)?;
|
|
Ok((play, song, chart))
|
|
})?
|
|
.next()
|
|
.ok_or_else(|| AppError::new(anyhow!("No recent plays found"), StatusCode::NOT_FOUND))??;
|
|
|
|
// Perhaps I need to make a Serialize-only version of this type which takes refs?
|
|
Ok(axum::response::Json(PlayWithDetails {
|
|
play,
|
|
song: song.clone(),
|
|
chart: chart.clone(),
|
|
}))
|
|
}
|