record-daemon: refactor, remove api_types entirely
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m5s
All checks were successful
record-daemon / Build, check and test (push) Successful in 2m5s
This commit is contained in:
@@ -1,369 +0,0 @@
|
|||||||
//! API response types for League Client API.
|
|
||||||
//!
|
|
||||||
//! These structs map directly to the JSON responses from the LQP REST API,
|
|
||||||
//! allowing automatic deserialization via serde.
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Summoner API Responses
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/// Response from `/lol-summoner/v1/current-summoner`
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct SummonerResponse {
|
|
||||||
/// Summoner ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Account ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub account_id: Option<u64>,
|
|
||||||
|
|
||||||
/// PUUID (globally unique identifier).
|
|
||||||
#[serde(default)]
|
|
||||||
pub puuid: Option<String>,
|
|
||||||
|
|
||||||
/// Display name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub display_name: Option<String>,
|
|
||||||
|
|
||||||
/// Internal name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub internal_name: Option<String>,
|
|
||||||
|
|
||||||
/// Name (legacy field).
|
|
||||||
#[serde(default)]
|
|
||||||
pub name: Option<String>,
|
|
||||||
|
|
||||||
/// Profile icon ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub profile_icon_id: Option<u32>,
|
|
||||||
|
|
||||||
/// Summoner level.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_level: Option<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Gameflow Session API Responses
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/// Response from `/lol-gameflow/v1/session`
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct GameflowSessionResponse {
|
|
||||||
/// Current gameflow phase.
|
|
||||||
#[serde(default)]
|
|
||||||
pub phase: Option<String>,
|
|
||||||
|
|
||||||
/// Game data (present when in game).
|
|
||||||
#[serde(default)]
|
|
||||||
pub game_data: Option<GameData>,
|
|
||||||
|
|
||||||
/// Map name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub map: Option<String>,
|
|
||||||
|
|
||||||
/// Game mode.
|
|
||||||
#[serde(default)]
|
|
||||||
pub game_mode: Option<String>,
|
|
||||||
|
|
||||||
/// Queue ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub queue_id: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Game data within a gameflow session.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct GameData {
|
|
||||||
/// Game ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub game_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Queue information.
|
|
||||||
#[serde(default)]
|
|
||||||
pub queue: Option<QueueData>,
|
|
||||||
|
|
||||||
/// Team one players.
|
|
||||||
#[serde(default)]
|
|
||||||
pub team_one: Option<Vec<TeamPlayer>>,
|
|
||||||
|
|
||||||
/// Team two players.
|
|
||||||
#[serde(default)]
|
|
||||||
pub team_two: Option<Vec<TeamPlayer>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Queue data within game data.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct QueueData {
|
|
||||||
/// Queue ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub id: Option<u64>,
|
|
||||||
|
|
||||||
/// Queue name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub name: Option<String>,
|
|
||||||
|
|
||||||
/// Game mode.
|
|
||||||
#[serde(default)]
|
|
||||||
pub game_mode: Option<String>,
|
|
||||||
|
|
||||||
/// Map ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub map_id: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Player in a team.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct TeamPlayer {
|
|
||||||
/// Player PUUID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub puuid: Option<String>,
|
|
||||||
|
|
||||||
/// Summoner name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_name: Option<String>,
|
|
||||||
|
|
||||||
/// Summoner ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Champion ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub champion_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Team ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub team_id: Option<u64>,
|
|
||||||
|
|
||||||
/// First summoner spell ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub spell1_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Second summoner spell ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub spell2_id: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Champion Select API Responses
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/// Response from `/lol-champ-select/v1/session`
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct ChampionSelectResponse {
|
|
||||||
/// Local player cell ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub local_player_cell_id: Option<i64>,
|
|
||||||
|
|
||||||
/// Timer information.
|
|
||||||
#[serde(default)]
|
|
||||||
pub timers: Option<Timers>,
|
|
||||||
|
|
||||||
/// My team.
|
|
||||||
#[serde(default)]
|
|
||||||
pub my_team: Option<Vec<ChampionSelectPlayer>>,
|
|
||||||
|
|
||||||
/// Their team.
|
|
||||||
#[serde(default)]
|
|
||||||
pub their_team: Option<Vec<ChampionSelectPlayer>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Timer information in champion select.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct Timers {
|
|
||||||
/// Current phase.
|
|
||||||
#[serde(default)]
|
|
||||||
pub phase: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Player in champion select.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct ChampionSelectPlayer {
|
|
||||||
/// Cell ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub cell_id: Option<i64>,
|
|
||||||
|
|
||||||
/// Champion ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub champion_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Champion name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub champion_name: Option<String>,
|
|
||||||
|
|
||||||
/// Team.
|
|
||||||
#[serde(default)]
|
|
||||||
pub team: Option<i64>,
|
|
||||||
|
|
||||||
/// Skin ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub skin_id: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Live Client Data API Responses
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/// Response from `/liveclientdata/activeplayer`
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct ActivePlayerResponse {
|
|
||||||
/// Active player's summoner name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_name: Option<String>,
|
|
||||||
|
|
||||||
/// Display name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub display_name: Option<String>,
|
|
||||||
|
|
||||||
/// Riot ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub riot_id: Option<String>,
|
|
||||||
|
|
||||||
/// Summoner spells.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_spells: Option<SummonerSpellsData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Summoner spells data from live client.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct SummonerSpellsData {
|
|
||||||
/// First summoner spell.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_spell_one: Option<SpellData>,
|
|
||||||
|
|
||||||
/// Second summoner spell.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_spell_two: Option<SpellData>,
|
|
||||||
|
|
||||||
/// First spell ID (alternative field).
|
|
||||||
#[serde(default)]
|
|
||||||
pub spell1_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Second spell ID (alternative field).
|
|
||||||
#[serde(default)]
|
|
||||||
pub spell2_id: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Individual spell data.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct SpellData {
|
|
||||||
/// Spell ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub spell_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Display name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub display_name: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Response from `/liveclientdata/playerlist`
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct PlayerListResponse(pub Vec<LiveClientPlayer>);
|
|
||||||
|
|
||||||
/// Player in live client data.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LiveClientPlayer {
|
|
||||||
/// Whether this is the local player.
|
|
||||||
#[serde(default)]
|
|
||||||
pub is_local_player: Option<bool>,
|
|
||||||
|
|
||||||
/// Summoner name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_name: Option<String>,
|
|
||||||
|
|
||||||
/// Riot ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub riot_id: Option<String>,
|
|
||||||
|
|
||||||
/// PUUID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub puuid: Option<String>,
|
|
||||||
|
|
||||||
/// Summoner ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub summoner_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Champion name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub champion_name: Option<String>,
|
|
||||||
|
|
||||||
/// Team.
|
|
||||||
#[serde(default)]
|
|
||||||
pub team: Option<u64>,
|
|
||||||
|
|
||||||
/// Items.
|
|
||||||
#[serde(default)]
|
|
||||||
pub items: Option<Vec<LiveClientItem>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Item in live client data.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LiveClientItem {
|
|
||||||
/// Item ID.
|
|
||||||
#[serde(default)]
|
|
||||||
pub item_id: Option<u64>,
|
|
||||||
|
|
||||||
/// Display name.
|
|
||||||
#[serde(default)]
|
|
||||||
pub display_name: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Helper implementations
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
impl ChampionSelectResponse {
|
|
||||||
/// Get the local player's champion selection.
|
|
||||||
pub fn get_local_player_selection(&self) -> Option<&ChampionSelectPlayer> {
|
|
||||||
let cell_id = self.local_player_cell_id?;
|
|
||||||
|
|
||||||
// Check my team first
|
|
||||||
if let Some(ref team) = self.my_team {
|
|
||||||
for player in team {
|
|
||||||
if player.cell_id == Some(cell_id) {
|
|
||||||
return Some(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check their team
|
|
||||||
if let Some(ref team) = self.their_team {
|
|
||||||
for player in team {
|
|
||||||
if player.cell_id == Some(cell_id) {
|
|
||||||
return Some(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_summoner_deserialization() {
|
|
||||||
let json = r#"{"summonerId": 12345, "puuid": "abc-123", "displayName": "TestPlayer"}"#;
|
|
||||||
let summoner: SummonerResponse = serde_json::from_str(json).unwrap();
|
|
||||||
assert_eq!(summoner.summoner_id, Some(12345));
|
|
||||||
assert_eq!(summoner.puuid, Some("abc-123".to_string()));
|
|
||||||
assert_eq!(summoner.display_name, Some("TestPlayer".to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,15 +5,10 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use tokio::sync::{broadcast, RwLock};
|
use tokio::sync::{broadcast, RwLock};
|
||||||
use tokio_tungstenite::{connect_async_tls_with_config, tungstenite::protocol::Message};
|
use tokio_tungstenite::{connect_async_tls_with_config, tungstenite::protocol::Message};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
use super::api_types::{
|
|
||||||
ActivePlayerResponse, ChampionSelectResponse, GameflowSessionResponse, PlayerListResponse,
|
|
||||||
SummonerResponse,
|
|
||||||
};
|
|
||||||
use super::auth::LockfileCredentials;
|
use super::auth::LockfileCredentials;
|
||||||
use super::endpoints;
|
use super::endpoints;
|
||||||
use super::events::GameEvent;
|
use super::events::GameEvent;
|
||||||
@@ -348,13 +343,6 @@ impl LqpClient {
|
|||||||
Ok(json)
|
Ok(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make a typed REST API request to the League Client.
|
|
||||||
async fn request_typed<T: DeserializeOwned>(&self, method: &str, endpoint: &str) -> Result<T> {
|
|
||||||
let json = self.request(method, endpoint).await?;
|
|
||||||
serde_json::from_value(json)
|
|
||||||
.map_err(|e| LqpError::EventParseError(format!("Deserialization failed: {}", e)).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the current gameflow phase.
|
/// Get the current gameflow phase.
|
||||||
pub async fn get_gameflow_phase(&self) -> Result<GameflowPhase> {
|
pub async fn get_gameflow_phase(&self) -> Result<GameflowPhase> {
|
||||||
let json = self.request("GET", endpoints::GAMEFLOW_PHASE).await?;
|
let json = self.request("GET", endpoints::GAMEFLOW_PHASE).await?;
|
||||||
@@ -364,31 +352,16 @@ impl LqpClient {
|
|||||||
Ok(GameflowPhase::from(phase_str))
|
Ok(GameflowPhase::from(phase_str))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current game session info (typed).
|
|
||||||
pub async fn get_session_typed(&self) -> Result<GameflowSessionResponse> {
|
|
||||||
self.request_typed("GET", endpoints::SESSION).await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the current game session info (raw JSON for backward compatibility).
|
/// Get the current game session info (raw JSON for backward compatibility).
|
||||||
pub async fn get_session(&self) -> Result<serde_json::Value> {
|
pub async fn get_session(&self) -> Result<serde_json::Value> {
|
||||||
self.request("GET", endpoints::SESSION).await
|
self.request("GET", endpoints::SESSION).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current summoner info (typed).
|
|
||||||
pub async fn get_summoner_typed(&self) -> Result<SummonerResponse> {
|
|
||||||
self.request_typed("GET", endpoints::SUMMONER).await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get current summoner info (raw JSON for backward compatibility).
|
/// Get current summoner info (raw JSON for backward compatibility).
|
||||||
pub async fn get_summoner(&self) -> Result<serde_json::Value> {
|
pub async fn get_summoner(&self) -> Result<serde_json::Value> {
|
||||||
self.request("GET", endpoints::SUMMONER).await
|
self.request("GET", endpoints::SUMMONER).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get champion select session info (typed).
|
|
||||||
pub async fn get_champion_select_typed(&self) -> Result<ChampionSelectResponse> {
|
|
||||||
self.request_typed("GET", endpoints::CHAMPION_SELECT).await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get champion select session info (raw JSON for backward compatibility).
|
/// Get champion select session info (raw JSON for backward compatibility).
|
||||||
pub async fn get_champion_select(&self) -> Result<serde_json::Value> {
|
pub async fn get_champion_select(&self) -> Result<serde_json::Value> {
|
||||||
self.request("GET", endpoints::CHAMPION_SELECT).await
|
self.request("GET", endpoints::CHAMPION_SELECT).await
|
||||||
@@ -424,24 +397,12 @@ impl LqpClient {
|
|||||||
self.request("GET", endpoints::LIVE_CLIENT_DATA).await
|
self.request("GET", endpoints::LIVE_CLIENT_DATA).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get active player data from live client (typed).
|
|
||||||
pub async fn get_live_client_active_player_typed(&self) -> Result<ActivePlayerResponse> {
|
|
||||||
self.request_typed("GET", endpoints::LIVE_CLIENT_DATA_ACTIVE_PLAYER)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get active player data from live client (raw JSON for backward compatibility).
|
/// Get active player data from live client (raw JSON for backward compatibility).
|
||||||
pub async fn get_live_client_active_player(&self) -> Result<serde_json::Value> {
|
pub async fn get_live_client_active_player(&self) -> Result<serde_json::Value> {
|
||||||
self.request("GET", endpoints::LIVE_CLIENT_DATA_ACTIVE_PLAYER)
|
self.request("GET", endpoints::LIVE_CLIENT_DATA_ACTIVE_PLAYER)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get player list from live client (typed).
|
|
||||||
pub async fn get_live_client_player_list_typed(&self) -> Result<PlayerListResponse> {
|
|
||||||
self.request_typed("GET", endpoints::LIVE_CLIENT_DATA_PLAYER_LIST)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get player list from live client (raw JSON for backward compatibility).
|
/// Get player list from live client (raw JSON for backward compatibility).
|
||||||
pub async fn get_live_client_player_list(&self) -> Result<serde_json::Value> {
|
pub async fn get_live_client_player_list(&self) -> Result<serde_json::Value> {
|
||||||
self.request("GET", endpoints::LIVE_CLIENT_DATA_PLAYER_LIST)
|
self.request("GET", endpoints::LIVE_CLIENT_DATA_PLAYER_LIST)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
//! This module handles communication with the League of Legends client
|
//! This module handles communication with the League of Legends client
|
||||||
//! via WebSocket and REST API for game event detection and capture.
|
//! via WebSocket and REST API for game event detection and capture.
|
||||||
|
|
||||||
mod api_types;
|
|
||||||
mod auth;
|
mod auth;
|
||||||
mod client;
|
mod client;
|
||||||
mod endpoints;
|
mod endpoints;
|
||||||
@@ -12,11 +11,6 @@ mod state;
|
|||||||
mod tls;
|
mod tls;
|
||||||
mod websocket;
|
mod websocket;
|
||||||
|
|
||||||
pub use api_types::{
|
|
||||||
ActivePlayerResponse, ChampionSelectPlayer, ChampionSelectResponse, GameData,
|
|
||||||
GameflowSessionResponse, LiveClientItem, LiveClientPlayer, PlayerListResponse, QueueData,
|
|
||||||
SummonerResponse, SummonerSpellsData, TeamPlayer, Timers,
|
|
||||||
};
|
|
||||||
pub use auth::{LockfileCredentials, LockfileWatcher};
|
pub use auth::{LockfileCredentials, LockfileWatcher};
|
||||||
pub use client::LqpClient;
|
pub use client::LqpClient;
|
||||||
pub use endpoints::{
|
pub use endpoints::{
|
||||||
|
|||||||
Reference in New Issue
Block a user