record-daemon: don't propagate puuid, record it and compute at end
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m10s

This commit is contained in:
2026-03-26 13:19:44 +01:00
parent 2814d85b6b
commit b94101c4d2
3 changed files with 20 additions and 74 deletions

View File

@@ -191,10 +191,7 @@ impl LqpClient {
if text.is_empty() {
continue;
}
// Get local_puuid from state for champion extraction
let local_puuid = state.read().await.local_puuid.clone();
if let Some(event) = parse_websocket_message(&text, local_puuid.as_deref())
{
if let Some(event) = parse_websocket_message(&text) {
// Update state based on event
Self::update_state_from_event(&state, &event).await;
@@ -227,11 +224,7 @@ impl LqpClient {
// Try to parse as UTF-8
if let Ok(text) = String::from_utf8(data) {
if !text.is_empty() {
// Get local_puuid from state for champion extraction
let local_puuid = state.read().await.local_puuid.clone();
if let Some(event) =
parse_websocket_message(&text, local_puuid.as_deref())
{
if let Some(event) = parse_websocket_message(&text) {
// Update state based on event
Self::update_state_from_event(&state, &event).await;

View File

@@ -6,10 +6,10 @@
use tracing::{debug, info, warn};
use super::events::{GameEvent, GameflowSession};
use super::mappings::{champion_id_to_name, map_id_to_name};
use super::mappings::map_id_to_name;
/// Parse a WebSocket message into a game event.
pub fn parse_websocket_message(text: &str, local_puuid: Option<&str>) -> Option<GameEvent> {
pub fn parse_websocket_message(text: &str) -> Option<GameEvent> {
// Parse the message array format: [type, callback, data]
let value: serde_json::Value = match serde_json::from_str(text) {
Ok(v) => v,
@@ -42,7 +42,6 @@ pub fn parse_websocket_message(text: &str, local_puuid: Option<&str>) -> Option<
&raw_event.uri,
event_type,
&serde_json::to_value(raw_event.data).unwrap_or_default(),
local_puuid,
);
}
@@ -54,7 +53,7 @@ pub fn parse_websocket_message(text: &str, local_puuid: Option<&str>) -> Option<
.and_then(|t| t.as_str())
.unwrap_or("Update");
return parse_event_from_uri(uri, event_type, data, local_puuid);
return parse_event_from_uri(uri, event_type, data);
} else {
debug!("Unknown callback: {}", callback);
}
@@ -80,7 +79,6 @@ pub fn parse_event_from_uri(
uri: &str,
event_type: &str,
data: &serde_json::Value,
local_puuid: Option<&str>,
) -> Option<GameEvent> {
info!("Parsing event from URI: {} (type: {})", uri, event_type);
@@ -91,7 +89,7 @@ pub fn parse_event_from_uri(
// Handle gameflow session updates
if uri == "/lol-gameflow/v1/session" {
return parse_gameflow_session_event(data, local_puuid);
return parse_gameflow_session_event(data);
}
// Handle game events (kills, deaths, objectives)
@@ -158,16 +156,13 @@ fn parse_gameflow_phase_event(data: &serde_json::Value) -> Option<GameEvent> {
}
/// Parse gameflow session event.
fn parse_gameflow_session_event(
data: &serde_json::Value,
local_puuid: Option<&str>,
) -> Option<GameEvent> {
fn parse_gameflow_session_event(data: &serde_json::Value) -> Option<GameEvent> {
if let Some(phase) = data.get("phase").and_then(|p| p.as_str()) {
info!("Gameflow session phase: {}", phase);
// Check for game start
if phase == "InProgress" {
return parse_game_start_event(data, local_puuid);
return parse_game_start_event(data);
}
return Some(
@@ -182,10 +177,10 @@ fn parse_gameflow_session_event(
}
/// Parse game start event from session data.
fn parse_game_start_event(
data: &serde_json::Value,
local_puuid: Option<&str>,
) -> Option<GameEvent> {
///
/// The session data contains all player information. The reading software should
/// use the puuid from RecordingMetadata to find the local player's data in the session.
fn parse_game_start_event(data: &serde_json::Value) -> Option<GameEvent> {
info!("Game is now in progress!");
// Try to parse the gameData into a GameflowSession struct
@@ -256,28 +251,10 @@ fn parse_game_start_event(
game_id, queue_type, queue_id, game_mode, map_name
);
// Extract player-specific data using puuid
let (champion, team, summoner_name) = if let Some(puuid) = local_puuid {
let champ_id = session.as_ref().and_then(|s| s.get_champion_id(puuid));
let team_id = session.as_ref().and_then(|s| s.get_team(puuid));
let summoner = session
.as_ref()
.and_then(|s| s.get_summoner_name(puuid))
.map(|s| s.to_string());
// Convert champion_id to champion name
let champ_name = champ_id.and_then(champion_id_to_name);
info!(
"Extracted player data via puuid: champion={:?}, team={:?}, summoner={:?}",
champ_name, team_id, summoner
);
(champ_name, team_id, summoner)
} else {
info!("No local_puuid available, cannot extract player-specific data");
(None, None, None)
};
// Note: Player-specific data (champion, team, summoner_name) is NOT extracted here.
// The full session is stored in the event, and the reading software should use
// the puuid from RecordingMetadata to find the local player's data in the session.
// This allows the same recording to be analyzed for any player by their puuid.
Some(
GameEvent::from_json(&serde_json::json!({
@@ -287,9 +264,6 @@ fn parse_game_start_event(
"queueId": queue_id,
"gameMode": game_mode,
"map": map_name,
"champion": champion,
"team": team,
"summonerName": summoner_name,
"session": session
}))
.unwrap_or(GameEvent::Unknown),
@@ -470,13 +444,13 @@ mod tests {
#[test]
fn test_parse_websocket_message_invalid_json() {
let result = parse_websocket_message("not json", None);
let result = parse_websocket_message("not json");
assert!(result.is_none());
}
#[test]
fn test_parse_websocket_message_empty_array() {
let result = parse_websocket_message("[]", None);
let result = parse_websocket_message("[]");
assert!(result.is_none());
}
}

View File

@@ -233,27 +233,6 @@ impl DaemonStateMachine {
match event {
GameEvent::GameStart(info) => {
// Extract summoner spells from session data if available
let summoner_spells = info.session.as_ref().and_then(|session| {
session
.player_champion_selections
.first()
.map(|selection| SummonerSpells {
spell1_id: selection.spell1_id,
spell2_id: selection.spell2_id,
spell1_name: crate::lqp::spell_id_to_name(selection.spell1_id),
spell2_name: crate::lqp::spell_id_to_name(selection.spell2_id),
})
});
// Extract puuid from session data if available
let puuid = info.session.as_ref().and_then(|session| {
session
.player_champion_selections
.first()
.map(|selection| selection.puuid.clone())
});
Some(StateTransition::GameStarted {
game_id: info.game_id,
champion: info.champion.clone(),
@@ -263,9 +242,9 @@ impl DaemonStateMachine {
map_name: info.map_name.clone(),
team: info.team,
summoner_name: info.summoner_name.clone(),
puuid,
puuid: None, // Will be populated from client.fetch_player_game_metadata()
runes: None, // Will be populated from client.fetch_player_game_metadata()
summoner_spells,
summoner_spells: None, // Will be populated from client.fetch_player_game_metadata()
})
}
GameEvent::GameEnd(info) => Some(StateTransition::GameEnded {