record-daemon: refactor/remove pregame metadata in daemon
record-daemon / Build, check and test (push) Successful in 2m0s
record-daemon / Build, check and test (push) Successful in 2m0s
This commit is contained in:
@@ -209,151 +209,6 @@ pub struct ChampionSelectPlayer {
|
||||
pub skin_id: Option<u64>,
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Rune Pages API Responses
|
||||
// =============================================================================
|
||||
|
||||
/// Response from `/lol-perks/v1/currentpage`
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RunePageResponse {
|
||||
/// Rune page ID.
|
||||
#[serde(default)]
|
||||
pub id: Option<u64>,
|
||||
|
||||
/// Rune page name.
|
||||
#[serde(default)]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Whether this is the current page.
|
||||
#[serde(default)]
|
||||
pub current: Option<bool>,
|
||||
|
||||
/// Primary style ID.
|
||||
#[serde(default)]
|
||||
pub primary_style_id: Option<u64>,
|
||||
|
||||
/// Secondary style ID.
|
||||
#[serde(default)]
|
||||
pub sub_style_id: Option<u64>,
|
||||
|
||||
/// Selected perk IDs.
|
||||
#[serde(default)]
|
||||
pub selected_perk_ids: Option<Vec<u64>>,
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// End of Game Stats API Responses
|
||||
// =============================================================================
|
||||
|
||||
/// Response from `/lol-end-of-game/v1/eog-stats-block`
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EndOfGameStatsResponse {
|
||||
/// Game ID.
|
||||
#[serde(default)]
|
||||
pub game_id: Option<u64>,
|
||||
|
||||
/// Game length in seconds.
|
||||
#[serde(default)]
|
||||
pub game_length: Option<f64>,
|
||||
|
||||
/// Match ID.
|
||||
#[serde(default)]
|
||||
pub match_id: Option<u64>,
|
||||
|
||||
/// Game result.
|
||||
#[serde(default)]
|
||||
pub game_result: Option<String>,
|
||||
|
||||
/// Local player data.
|
||||
#[serde(default)]
|
||||
pub local_player: Option<EndOfGamePlayer>,
|
||||
|
||||
/// Teams data.
|
||||
#[serde(default)]
|
||||
pub teams: Option<Vec<EndOfGameTeam>>,
|
||||
|
||||
/// Players (legacy format).
|
||||
#[serde(default)]
|
||||
pub players: Option<Vec<EndOfGamePlayer>>,
|
||||
}
|
||||
|
||||
/// Player in end-of-game stats.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EndOfGamePlayer {
|
||||
/// Whether this is the local player.
|
||||
#[serde(default)]
|
||||
pub is_local_player: Option<bool>,
|
||||
|
||||
/// Player stats.
|
||||
#[serde(default)]
|
||||
pub stats: Option<PlayerStats>,
|
||||
|
||||
/// Items.
|
||||
#[serde(default)]
|
||||
pub items: Option<Vec<u64>>,
|
||||
}
|
||||
|
||||
/// Team in end-of-game stats.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EndOfGameTeam {
|
||||
/// Whether this is the player's team.
|
||||
#[serde(default)]
|
||||
pub is_player_team: Option<bool>,
|
||||
|
||||
/// Whether this is the winning team.
|
||||
#[serde(default)]
|
||||
pub is_winning_team: Option<bool>,
|
||||
|
||||
/// Players on the team.
|
||||
#[serde(default)]
|
||||
pub players: Option<Vec<EndOfGamePlayer>>,
|
||||
}
|
||||
|
||||
/// Player stats in end-of-game.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
pub struct PlayerStats {
|
||||
/// Kills.
|
||||
#[serde(default)]
|
||||
pub champions_killed: Option<u64>,
|
||||
|
||||
/// Deaths.
|
||||
#[serde(default)]
|
||||
pub num_deaths: Option<u64>,
|
||||
|
||||
/// Assists.
|
||||
#[serde(default)]
|
||||
pub assists: Option<u64>,
|
||||
|
||||
/// Minions killed (CS).
|
||||
#[serde(default)]
|
||||
pub minions_killed: Option<u64>,
|
||||
|
||||
/// Gold earned.
|
||||
#[serde(default)]
|
||||
pub gold_earned: Option<u64>,
|
||||
|
||||
/// Total damage dealt to champions.
|
||||
#[serde(default)]
|
||||
pub total_damage_dealt_to_champions: Option<u64>,
|
||||
|
||||
/// Total damage taken.
|
||||
#[serde(default)]
|
||||
pub total_damage_taken: Option<u64>,
|
||||
|
||||
/// Vision score.
|
||||
#[serde(default)]
|
||||
pub vision_score: Option<f64>,
|
||||
|
||||
/// Win status (1 = win).
|
||||
#[serde(default)]
|
||||
pub win: Option<u64>,
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Live Client Data API Responses
|
||||
// =============================================================================
|
||||
@@ -472,59 +327,6 @@ pub struct LiveClientItem {
|
||||
// Helper implementations
|
||||
// =============================================================================
|
||||
|
||||
impl EndOfGameStatsResponse {
|
||||
/// Get the local player from the response.
|
||||
pub fn get_local_player(&self) -> Option<&EndOfGamePlayer> {
|
||||
// First check local_player field
|
||||
if let Some(ref player) = self.local_player {
|
||||
return Some(player);
|
||||
}
|
||||
|
||||
// Then check teams
|
||||
if let Some(ref teams) = self.teams {
|
||||
for team in teams {
|
||||
if let Some(ref players) = team.players {
|
||||
for player in players {
|
||||
if player.is_local_player == Some(true) {
|
||||
return Some(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally check legacy players array
|
||||
if let Some(ref players) = self.players {
|
||||
return players.first();
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Check if the local player won.
|
||||
pub fn is_victory(&self) -> bool {
|
||||
// Check local player stats
|
||||
if let Some(player) = self.get_local_player() {
|
||||
if let Some(ref stats) = player.stats {
|
||||
if stats.win == Some(1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check teams
|
||||
if let Some(ref teams) = self.teams {
|
||||
for team in teams {
|
||||
if team.is_player_team == Some(true) && team.is_winning_team == Some(true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ChampionSelectResponse {
|
||||
/// Get the local player's champion selection.
|
||||
pub fn get_local_player_selection(&self) -> Option<&ChampionSelectPlayer> {
|
||||
@@ -552,80 +354,6 @@ impl ChampionSelectResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Aggregated Data Containers
|
||||
// =============================================================================
|
||||
|
||||
/// Container for pre-game data collected from multiple API calls.
|
||||
/// Stores raw API responses directly for maximum flexibility.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct PreGameData {
|
||||
/// Session data (map, game mode, queue info).
|
||||
pub session: Option<GameflowSessionResponse>,
|
||||
/// Summoner data (puuid, name).
|
||||
pub summoner: Option<SummonerResponse>,
|
||||
/// Champion select data (champion, skin, team).
|
||||
pub champion_select: Option<ChampionSelectResponse>,
|
||||
/// Rune page data.
|
||||
pub rune_page: Option<RunePageResponse>,
|
||||
}
|
||||
|
||||
impl PreGameData {
|
||||
/// Get the summoner name from any available source.
|
||||
pub fn summoner_name(&self) -> Option<&str> {
|
||||
self.summoner
|
||||
.as_ref()
|
||||
.and_then(|s| s.display_name.as_deref())
|
||||
.or_else(|| self.summoner.as_ref().and_then(|s| s.name.as_deref()))
|
||||
}
|
||||
|
||||
/// Get the PUUID.
|
||||
pub fn puuid(&self) -> Option<&str> {
|
||||
self.summoner.as_ref()?.puuid.as_deref()
|
||||
}
|
||||
|
||||
/// Get the champion ID from champion select.
|
||||
pub fn champion_id(&self) -> Option<u64> {
|
||||
let cs = self.champion_select.as_ref()?;
|
||||
let player = cs.get_local_player_selection()?;
|
||||
player.champion_id
|
||||
}
|
||||
|
||||
/// Get the team ID from champion select.
|
||||
pub fn team(&self) -> Option<i64> {
|
||||
let cs = self.champion_select.as_ref()?;
|
||||
let player = cs.get_local_player_selection()?;
|
||||
player.team
|
||||
}
|
||||
|
||||
/// Get the skin ID from champion select.
|
||||
pub fn skin_id(&self) -> Option<u64> {
|
||||
let cs = self.champion_select.as_ref()?;
|
||||
let player = cs.get_local_player_selection()?;
|
||||
player.skin_id
|
||||
}
|
||||
|
||||
/// Get the map name from session.
|
||||
pub fn map_name(&self) -> Option<&str> {
|
||||
self.session.as_ref()?.map.as_deref()
|
||||
}
|
||||
|
||||
/// Get the game mode from session.
|
||||
pub fn game_mode(&self) -> Option<&str> {
|
||||
self.session.as_ref()?.game_mode.as_deref()
|
||||
}
|
||||
|
||||
/// Get the queue ID from session.
|
||||
pub fn queue_id(&self) -> Option<u64> {
|
||||
self.session.as_ref()?.queue_id
|
||||
}
|
||||
|
||||
/// Get the rune page name.
|
||||
pub fn rune_page_name(&self) -> Option<&str> {
|
||||
self.rune_page.as_ref()?.name.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -638,13 +366,4 @@ mod tests {
|
||||
assert_eq!(summoner.puuid, Some("abc-123".to_string()));
|
||||
assert_eq!(summoner.display_name, Some("TestPlayer".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_player_stats_deserialization() {
|
||||
let json = r#"{"CHAMPIONS_KILLED": 10, "NUM_DEATHS": 3, "ASSISTS": 15}"#;
|
||||
let stats: PlayerStats = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(stats.champions_killed, Some(10));
|
||||
assert_eq!(stats.num_deaths, Some(3));
|
||||
assert_eq!(stats.assists, Some(15));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ use tokio_tungstenite::{connect_async_tls_with_config, tungstenite::protocol::Me
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
|
||||
use super::api_types::{
|
||||
ActivePlayerResponse, ChampionSelectResponse, EndOfGameStatsResponse, GameflowSessionResponse,
|
||||
PlayerListResponse, PreGameData, RunePageResponse, SummonerResponse,
|
||||
ActivePlayerResponse, ChampionSelectResponse, GameflowSessionResponse, PlayerListResponse,
|
||||
SummonerResponse,
|
||||
};
|
||||
use super::auth::LockfileCredentials;
|
||||
use super::endpoints;
|
||||
@@ -394,11 +394,6 @@ impl LqpClient {
|
||||
self.request("GET", endpoints::CHAMPION_SELECT).await
|
||||
}
|
||||
|
||||
/// Get end-of-game stats (typed).
|
||||
pub async fn get_game_stats_typed(&self) -> Result<EndOfGameStatsResponse> {
|
||||
self.request_typed("GET", endpoints::GAME_STATS).await
|
||||
}
|
||||
|
||||
/// Get end-of-game stats (raw JSON for backward compatibility).
|
||||
pub async fn get_game_stats(&self) -> Result<serde_json::Value> {
|
||||
self.request("GET", endpoints::GAME_STATS).await
|
||||
@@ -409,11 +404,6 @@ impl LqpClient {
|
||||
self.request("GET", endpoints::CHAMPION_SUMMARY).await
|
||||
}
|
||||
|
||||
/// Get current rune page (typed).
|
||||
pub async fn get_rune_page_typed(&self) -> Result<RunePageResponse> {
|
||||
self.request_typed("GET", endpoints::RUNE_PAGES).await
|
||||
}
|
||||
|
||||
/// Get current rune page (raw JSON for backward compatibility).
|
||||
pub async fn get_rune_page(&self) -> Result<serde_json::Value> {
|
||||
self.request("GET", endpoints::RUNE_PAGES).await
|
||||
@@ -497,49 +487,6 @@ impl LqpClient {
|
||||
pub async fn fetch_raw_end_game_stats(&self) -> Result<serde_json::Value> {
|
||||
self.request("GET", endpoints::GAME_STATS).await
|
||||
}
|
||||
|
||||
/// Fetch pre-game data (stores raw API responses directly).
|
||||
pub async fn fetch_pregame_data(&self) -> Result<PreGameData> {
|
||||
let mut data = PreGameData::default();
|
||||
|
||||
// Fetch all API responses in parallel where possible
|
||||
let (session, summoner, champ_select, rune_page) = tokio::join!(
|
||||
self.get_session_typed(),
|
||||
self.get_summoner_typed(),
|
||||
self.get_champion_select_typed(),
|
||||
self.get_rune_page_typed()
|
||||
);
|
||||
|
||||
// Store session data
|
||||
if let Ok(session) = session {
|
||||
data.session = Some(session);
|
||||
}
|
||||
|
||||
// Store summoner data and update state
|
||||
if let Ok(summoner) = summoner {
|
||||
if let Some(ref puuid) = summoner.puuid {
|
||||
self.state.write().await.local_puuid = Some(puuid.clone());
|
||||
}
|
||||
data.summoner = Some(summoner);
|
||||
}
|
||||
|
||||
// Store champion select data
|
||||
if let Ok(champ_select) = champ_select {
|
||||
data.champion_select = Some(champ_select);
|
||||
}
|
||||
|
||||
// Store rune page data
|
||||
if let Ok(rune_page) = rune_page {
|
||||
data.rune_page = Some(rune_page);
|
||||
}
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
/// Fetch end-of-game stats (returns raw API response).
|
||||
pub async fn fetch_game_end_stats(&self) -> Result<EndOfGameStatsResponse> {
|
||||
self.get_game_stats_typed().await
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LqpClient {
|
||||
|
||||
@@ -13,9 +13,8 @@ mod tls;
|
||||
mod websocket;
|
||||
|
||||
pub use api_types::{
|
||||
ActivePlayerResponse, ChampionSelectPlayer, ChampionSelectResponse, EndOfGamePlayer,
|
||||
EndOfGameStatsResponse, EndOfGameTeam, GameData, GameflowSessionResponse, LiveClientItem,
|
||||
LiveClientPlayer, PlayerListResponse, PlayerStats, PreGameData, QueueData, RunePageResponse,
|
||||
ActivePlayerResponse, ChampionSelectPlayer, ChampionSelectResponse, GameData,
|
||||
GameflowSessionResponse, LiveClientItem, LiveClientPlayer, PlayerListResponse, QueueData,
|
||||
SummonerResponse, SummonerSpellsData, TeamPlayer, Timers,
|
||||
};
|
||||
pub use auth::{LockfileCredentials, LockfileWatcher};
|
||||
|
||||
Reference in New Issue
Block a user