From 18a45f664b1f514571f985b5d4a9aa87071420e7 Mon Sep 17 00:00:00 2001 From: FURRO404 Date: Thu, 18 Jun 2026 00:32:51 -0700 Subject: [PATCH] feat(backend): /api/tss/games/:id/logs endpoint --- backend/src/main.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/backend/src/main.rs b/backend/src/main.rs index f35f57b..ab54b06 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -214,6 +214,12 @@ struct GameResponse { participants: Vec, } +#[derive(Serialize)] +struct GameLogsResponse { + chat_log: Vec, + battle_log: Vec, +} + #[derive(Serialize)] struct GameRow { #[serde(skip_serializing_if = "Option::is_none")] @@ -358,6 +364,7 @@ async fn main() -> Result<(), Box> { .route("/api/tss/leaderboard/teams", get(leaderboard)) .route("/api/tss/games/recent", get(recent_games)) .route("/api/tss/games/{session_id}", get(game_detail)) + .route("/api/tss/games/{session_id}/logs", get(game_logs)) .route("/api/tss/teams/resolve", get(resolve_team)) .route("/api/tss/teams/search", get(search_teams)) .route("/api/tss/teams/{team}", get(team_detail)) @@ -564,6 +571,31 @@ async fn game_detail( Ok(Json(GameResponse { game, participants })) } +async fn game_logs( + State(state): State>, + Path(session_id): Path, +) -> ApiResult { + let session_id = validate_session_id(&session_id)?; + let conn = open_db(&state.battles_db)?; + // Logs are non-critical: a missing match_logs table or row yields empty arrays. + let row: Option<(Option, Option)> = conn + .query_row( + "SELECT chat_log_json, battle_log_json FROM match_logs WHERE session_id = ?1", + params![session_id], + |r| Ok((r.get(0)?, r.get(1)?)), + ) + .optional() + .unwrap_or(None); + let parse = |s: Option| -> Vec { + s.and_then(|t| serde_json::from_str(&t).ok()).unwrap_or_default() + }; + let (chat, battle) = row.unwrap_or((None, None)); + Ok(Json(GameLogsResponse { + chat_log: parse(chat), + battle_log: parse(battle), + })) +} + async fn resolve_team( State(state): State>, Query(query): Query,