record-daemon: fmt, clippy
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m12s
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m12s
This commit is contained in:
@@ -976,17 +976,20 @@ impl LqpClient {
|
||||
|
||||
/// Get active player data from live client.
|
||||
pub async fn get_live_client_active_player(&self) -> Result<serde_json::Value> {
|
||||
self.request("GET", endpoints::LIVE_CLIENT_DATA_ACTIVE_PLAYER).await
|
||||
self.request("GET", endpoints::LIVE_CLIENT_DATA_ACTIVE_PLAYER)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Get player list from live client (contains all players with puuid and summoner names).
|
||||
pub async fn get_live_client_player_list(&self) -> Result<serde_json::Value> {
|
||||
self.request("GET", endpoints::LIVE_CLIENT_DATA_PLAYER_LIST).await
|
||||
self.request("GET", endpoints::LIVE_CLIENT_DATA_PLAYER_LIST)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Get local player selection from champion select.
|
||||
pub async fn get_local_player_selection(&self) -> Result<serde_json::Value> {
|
||||
self.request("GET", endpoints::CHAMPION_SELECT_LOCAL_PLAYER).await
|
||||
self.request("GET", endpoints::CHAMPION_SELECT_LOCAL_PLAYER)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Fetch pre-game metadata (champion, skin, runes, queue info).
|
||||
@@ -1130,9 +1133,13 @@ impl LqpClient {
|
||||
|
||||
// Get summoner info - try multiple field names for summoner name
|
||||
if let Ok(summoner) = self.get_summoner().await {
|
||||
metadata.puuid = summoner.get("puuid").and_then(|p| p.as_str()).map(|s| s.to_string());
|
||||
metadata.puuid = summoner
|
||||
.get("puuid")
|
||||
.and_then(|p| p.as_str())
|
||||
.map(|s| s.to_string());
|
||||
// Try displayName first, then name, then internalName
|
||||
metadata.summoner_name = summoner.get("displayName")
|
||||
metadata.summoner_name = summoner
|
||||
.get("displayName")
|
||||
.or_else(|| summoner.get("name"))
|
||||
.or_else(|| summoner.get("internalName"))
|
||||
.and_then(|n| n.as_str())
|
||||
@@ -1141,8 +1148,14 @@ impl LqpClient {
|
||||
|
||||
// Get rune page
|
||||
if let Ok(rune_page) = self.get_rune_page().await {
|
||||
let primary_style_id = rune_page.get("primaryStyleId").and_then(|id| id.as_u64()).unwrap_or(0) as u32;
|
||||
let secondary_style_id = rune_page.get("subStyleId").and_then(|id| id.as_u64()).unwrap_or(0) as u32;
|
||||
let primary_style_id = rune_page
|
||||
.get("primaryStyleId")
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or(0) as u32;
|
||||
let secondary_style_id = rune_page
|
||||
.get("subStyleId")
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or(0) as u32;
|
||||
let selected_perks = rune_page
|
||||
.get("selectedPerkIds")
|
||||
.and_then(|ids| ids.as_array())
|
||||
@@ -1159,37 +1172,57 @@ impl LqpClient {
|
||||
secondary_style_id,
|
||||
selected_perks,
|
||||
stat_modifiers: Vec::new(), // Stat modifiers are part of selectedPerkIds
|
||||
name: rune_page.get("name").and_then(|n| n.as_str()).map(|s| s.to_string()),
|
||||
current: rune_page.get("current").and_then(|c| c.as_bool()).unwrap_or(true),
|
||||
name: rune_page
|
||||
.get("name")
|
||||
.and_then(|n| n.as_str())
|
||||
.map(|s| s.to_string()),
|
||||
current: rune_page
|
||||
.get("current")
|
||||
.and_then(|c| c.as_bool())
|
||||
.unwrap_or(true),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get summoner spells from live client data (available during game)
|
||||
if let Ok(active_player) = self.get_live_client_active_player().await {
|
||||
debug!("[METADATA] Live client active player data: {:?}", active_player);
|
||||
|
||||
debug!(
|
||||
"[METADATA] Live client active player data: {:?}",
|
||||
active_player
|
||||
);
|
||||
|
||||
// Get summoner spells from active player - try multiple field structures
|
||||
if let Some(summoner_spells) = active_player.get("summonerSpells") {
|
||||
// Try nested structure first: summonerSpells.summonerSpellOne.spellId
|
||||
let spell1_id = summoner_spells.get("summonerSpellOne")
|
||||
let spell1_id = summoner_spells
|
||||
.get("summonerSpellOne")
|
||||
.and_then(|s| s.get("spellId"))
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or_else(|| {
|
||||
// Fallback: direct spell1Id field
|
||||
summoner_spells.get("spell1Id").and_then(|id| id.as_u64()).unwrap_or(0)
|
||||
summoner_spells
|
||||
.get("spell1Id")
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or(0)
|
||||
}) as u32;
|
||||
|
||||
let spell2_id = summoner_spells.get("summonerSpellTwo")
|
||||
|
||||
let spell2_id = summoner_spells
|
||||
.get("summonerSpellTwo")
|
||||
.and_then(|s| s.get("spellId"))
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or_else(|| {
|
||||
// Fallback: direct spell2Id field
|
||||
summoner_spells.get("spell2Id").and_then(|id| id.as_u64()).unwrap_or(0)
|
||||
summoner_spells
|
||||
.get("spell2Id")
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or(0)
|
||||
}) as u32;
|
||||
|
||||
debug!("[METADATA] Summoner spells from live client: spell1={}, spell2={}", spell1_id, spell2_id);
|
||||
|
||||
|
||||
debug!(
|
||||
"[METADATA] Summoner spells from live client: spell1={}, spell2={}",
|
||||
spell1_id, spell2_id
|
||||
);
|
||||
|
||||
if spell1_id > 0 || spell2_id > 0 {
|
||||
metadata.summoner_spells = Some(SummonerSpells {
|
||||
spell1_id,
|
||||
@@ -1199,10 +1232,13 @@ impl LqpClient {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get summoner name from active player if not already set
|
||||
if metadata.summoner_name.is_none() || metadata.summoner_name.as_ref().map_or(true, |n| n.is_empty()) {
|
||||
metadata.summoner_name = active_player.get("summonerName")
|
||||
if metadata.summoner_name.is_none()
|
||||
|| metadata.summoner_name.as_ref().is_none_or(|n| n.is_empty())
|
||||
{
|
||||
metadata.summoner_name = active_player
|
||||
.get("summonerName")
|
||||
.or_else(|| active_player.get("displayName"))
|
||||
.or_else(|| active_player.get("riotId"))
|
||||
.and_then(|n| n.as_str())
|
||||
@@ -1220,10 +1256,20 @@ impl LqpClient {
|
||||
for team_key in &["teamOne", "teamTwo"] {
|
||||
if let Some(team) = game_data.get(team_key).and_then(|t| t.as_array()) {
|
||||
for player in team {
|
||||
if player.get("puuid").and_then(|p| p.as_str()) == Some(local_puuid.as_str()) {
|
||||
let spell1_id = player.get("spell1Id").and_then(|id| id.as_u64()).unwrap_or(0) as u32;
|
||||
let spell2_id = player.get("spell2Id").and_then(|id| id.as_u64()).unwrap_or(0) as u32;
|
||||
|
||||
if player.get("puuid").and_then(|p| p.as_str())
|
||||
== Some(local_puuid.as_str())
|
||||
{
|
||||
let spell1_id = player
|
||||
.get("spell1Id")
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or(0)
|
||||
as u32;
|
||||
let spell2_id = player
|
||||
.get("spell2Id")
|
||||
.and_then(|id| id.as_u64())
|
||||
.unwrap_or(0)
|
||||
as u32;
|
||||
|
||||
if spell1_id > 0 || spell2_id > 0 {
|
||||
metadata.summoner_spells = Some(SummonerSpells {
|
||||
spell1_id,
|
||||
@@ -1232,9 +1278,15 @@ impl LqpClient {
|
||||
spell2_name: spell_id_to_name(spell2_id),
|
||||
});
|
||||
}
|
||||
|
||||
metadata.champion_id = player.get("championId").and_then(|id| id.as_u64()).map(|v| v as u32);
|
||||
metadata.team = player.get("teamId").and_then(|id| id.as_u64()).map(|v| v as u32);
|
||||
|
||||
metadata.champion_id = player
|
||||
.get("championId")
|
||||
.and_then(|id| id.as_u64())
|
||||
.map(|v| v as u32);
|
||||
metadata.team = player
|
||||
.get("teamId")
|
||||
.and_then(|id| id.as_u64())
|
||||
.map(|v| v as u32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1263,19 +1315,24 @@ impl LqpClient {
|
||||
if let Some(arr) = player_list.as_array() {
|
||||
for player in arr {
|
||||
// Get summoner name - try multiple fields
|
||||
let summoner_name = player.get("summonerName")
|
||||
let summoner_name = player
|
||||
.get("summonerName")
|
||||
.or_else(|| player.get("riotId"))
|
||||
.and_then(|n| n.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
|
||||
// Get team from teamId
|
||||
let team = player.get("team").and_then(|t| t.as_u64()).map(|v| v as u32);
|
||||
|
||||
let team = player
|
||||
.get("team")
|
||||
.and_then(|t| t.as_u64())
|
||||
.map(|v| v as u32);
|
||||
|
||||
// Get champion name
|
||||
let champion_name = player.get("championName")
|
||||
let champion_name = player
|
||||
.get("championName")
|
||||
.and_then(|n| n.as_str())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
|
||||
if let Some(puuid) = player.get("puuid").and_then(|p| p.as_str()) {
|
||||
players.push(super::PlayerIdentity {
|
||||
puuid: puuid.to_string(),
|
||||
@@ -1294,19 +1351,28 @@ impl LqpClient {
|
||||
if let Ok(session) = self.get_session().await {
|
||||
if let Some(game_data) = session.get("gameData") {
|
||||
for team_key in &["teamOne", "teamTwo"] {
|
||||
let team_id = if *team_key == "teamOne" { 100u32 } else { 200u32 };
|
||||
let team_id = if *team_key == "teamOne" {
|
||||
100u32
|
||||
} else {
|
||||
200u32
|
||||
};
|
||||
if let Some(team) = game_data.get(team_key).and_then(|t| t.as_array()) {
|
||||
for player in team {
|
||||
if let (Some(puuid), Some(summoner_name)) = (
|
||||
player.get("puuid").and_then(|p| p.as_str()),
|
||||
player.get("summonerName").and_then(|n| n.as_str()),
|
||||
) {
|
||||
let champion_id = player.get("championId").and_then(|id| id.as_u64()).map(|v| v as u32);
|
||||
let champion_name = champion_id.and_then(|id| champion_id_to_name(id));
|
||||
let champion_id = player
|
||||
.get("championId")
|
||||
.and_then(|id| id.as_u64())
|
||||
.map(|v| v as u32);
|
||||
let champion_name = champion_id.and_then(champion_id_to_name);
|
||||
players.push(super::PlayerIdentity {
|
||||
puuid: puuid.to_string(),
|
||||
summoner_name: summoner_name.to_string(),
|
||||
summoner_id: player.get("summonerId").and_then(|id| id.as_u64()),
|
||||
summoner_id: player
|
||||
.get("summonerId")
|
||||
.and_then(|id| id.as_u64()),
|
||||
champion_name,
|
||||
team: Some(team_id),
|
||||
});
|
||||
@@ -1324,24 +1390,35 @@ impl LqpClient {
|
||||
/// Fetch final items from end-of-game stats or live client data.
|
||||
pub async fn fetch_final_items(&self) -> Result<Option<super::ItemBuild>> {
|
||||
info!("[ITEMS] Fetching final items...");
|
||||
|
||||
|
||||
// First try live client data (available during game)
|
||||
match self.get_live_client_player_list().await {
|
||||
Ok(player_list) => {
|
||||
info!("[ITEMS] Live client player list response: {:?}", player_list);
|
||||
info!(
|
||||
"[ITEMS] Live client player list response: {:?}",
|
||||
player_list
|
||||
);
|
||||
if let Some(players) = player_list.as_array() {
|
||||
info!("[ITEMS] Found {} players in live client data", players.len());
|
||||
info!(
|
||||
"[ITEMS] Found {} players in live client data",
|
||||
players.len()
|
||||
);
|
||||
// Find the local player (first player or one with matching puuid)
|
||||
for player in players {
|
||||
// Check if this is the local player
|
||||
let is_local = player.get("isLocalPlayer").and_then(|l| l.as_bool()).unwrap_or(false);
|
||||
let is_local = player
|
||||
.get("isLocalPlayer")
|
||||
.and_then(|l| l.as_bool())
|
||||
.unwrap_or(false);
|
||||
if is_local {
|
||||
info!("[ITEMS] Found local player in live client data");
|
||||
if let Some(items) = player.get("items").and_then(|i| i.as_array()) {
|
||||
info!("[ITEMS] Items array has {} items", items.len());
|
||||
let item_build = self.parse_items_from_live_client(items);
|
||||
if item_build.is_some() {
|
||||
info!("[ITEMS] Successfully parsed items from live client data");
|
||||
info!(
|
||||
"[ITEMS] Successfully parsed items from live client data"
|
||||
);
|
||||
return Ok(item_build);
|
||||
}
|
||||
} else {
|
||||
@@ -1360,7 +1437,7 @@ impl LqpClient {
|
||||
match self.get_game_stats().await {
|
||||
Ok(stats) => {
|
||||
info!("[ITEMS] Game stats response received");
|
||||
|
||||
|
||||
// First try localPlayer field (items are just numbers in an array)
|
||||
if let Some(local_player) = stats.get("localPlayer") {
|
||||
info!("[ITEMS] Found localPlayer in game stats");
|
||||
@@ -1373,18 +1450,26 @@ impl LqpClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try teams[].players[] structure
|
||||
if let Some(teams) = stats.get("teams").and_then(|t| t.as_array()) {
|
||||
info!("[ITEMS] Found {} teams in game stats", teams.len());
|
||||
for team in teams {
|
||||
if let Some(players) = team.get("players").and_then(|p| p.as_array()) {
|
||||
for player in players {
|
||||
let is_local = player.get("isLocalPlayer").and_then(|l| l.as_bool()).unwrap_or(false);
|
||||
let is_local = player
|
||||
.get("isLocalPlayer")
|
||||
.and_then(|l| l.as_bool())
|
||||
.unwrap_or(false);
|
||||
if is_local {
|
||||
info!("[ITEMS] Found local player in teams[].players[]");
|
||||
if let Some(items) = player.get("items").and_then(|i| i.as_array()) {
|
||||
info!("[ITEMS] Player items array has {} items", items.len());
|
||||
if let Some(items) =
|
||||
player.get("items").and_then(|i| i.as_array())
|
||||
{
|
||||
info!(
|
||||
"[ITEMS] Player items array has {} items",
|
||||
items.len()
|
||||
);
|
||||
let item_build = self.parse_items_from_game_stats(items);
|
||||
if item_build.is_some() {
|
||||
info!("[ITEMS] Successfully parsed items from teams[].players[]");
|
||||
@@ -1396,10 +1481,13 @@ impl LqpClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try old players array structure (for backwards compatibility)
|
||||
if let Some(players) = stats.get("players").and_then(|p| p.as_array()) {
|
||||
info!("[ITEMS] Found {} players in game stats (legacy)", players.len());
|
||||
info!(
|
||||
"[ITEMS] Found {} players in game stats (legacy)",
|
||||
players.len()
|
||||
);
|
||||
if let Some(player) = players.first() {
|
||||
if let Some(items) = player.get("items").and_then(|i| i.as_array()) {
|
||||
let item_build = self.parse_items_from_game_stats(items);
|
||||
@@ -1409,7 +1497,7 @@ impl LqpClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
info!("[ITEMS] Could not find items in game stats structure");
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -1422,7 +1510,10 @@ impl LqpClient {
|
||||
}
|
||||
|
||||
/// Parse items from live client data format.
|
||||
fn parse_items_from_live_client(&self, items: &[serde_json::Value]) -> Option<super::ItemBuild> {
|
||||
fn parse_items_from_live_client(
|
||||
&self,
|
||||
items: &[serde_json::Value],
|
||||
) -> Option<super::ItemBuild> {
|
||||
let mut item_list = Vec::new();
|
||||
let mut trinket = None;
|
||||
|
||||
@@ -1431,7 +1522,10 @@ impl LqpClient {
|
||||
if item_id > 0 {
|
||||
let item_info = ItemInfo {
|
||||
item_id: item_id as u32,
|
||||
name: item.get("displayName").and_then(|n| n.as_str()).map(|s| s.to_string()),
|
||||
name: item
|
||||
.get("displayName")
|
||||
.and_then(|n| n.as_str())
|
||||
.map(|s| s.to_string()),
|
||||
slot: slot as u32,
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ mod client;
|
||||
mod events;
|
||||
|
||||
pub use auth::{LockfileCredentials, LockfileWatcher};
|
||||
pub use client::{champion_id_to_name, spell_id_to_name, GameEndMetadata, GameflowPhase, LqpClient, PreGameMetadata};
|
||||
pub use client::{
|
||||
champion_id_to_name, spell_id_to_name, GameEndMetadata, GameflowPhase, LqpClient,
|
||||
PreGameMetadata,
|
||||
};
|
||||
pub use events::{
|
||||
ChampSelectStartInfo, ChampionPickInfo, DeathEvent, EventData, GameEndInfo, GameEvent,
|
||||
GameStartInfo, GameflowSession, InGameStats, ItemBuild, ItemInfo, KillEvent, MatchInfo,
|
||||
|
||||
Reference in New Issue
Block a user