record-daemon: fix obs recording

This commit is contained in:
2026-03-20 20:34:44 +01:00
parent dbb224e118
commit 1166424c29
12 changed files with 3717 additions and 515 deletions

View File

@@ -243,13 +243,12 @@ impl LqpClient {
// Create a TLS connector that accepts the self-signed certificate from League Client
use tokio_tungstenite::Connector;
use tokio_tungstenite::tungstenite::http::HeaderValue;
let config = rustls::ClientConfig::builder()
.dangerous()
.with_custom_certificate_verifier(Arc::new(InsecureVerifier))
.with_no_client_auth();
let connector = Connector::Rustls(Arc::new(config));
// Build WebSocket request with auth header
@@ -260,18 +259,16 @@ impl LqpClient {
.header("Connection", "Upgrade")
.header("Upgrade", "websocket")
.header("Sec-WebSocket-Version", "13")
.header("Sec-WebSocket-Key", tokio_tungstenite::tungstenite::handshake::client::generate_key())
.header(
"Sec-WebSocket-Key",
tokio_tungstenite::tungstenite::handshake::client::generate_key(),
)
.body(())
.map_err(|e| LqpError::ConnectionFailed(e.to_string()))?;
let (ws_stream, _) = connect_async_tls_with_config(
request,
None,
false,
Some(connector),
)
.await
.map_err(|e| LqpError::WebSocketError(e.to_string()))?;
let (ws_stream, _) = connect_async_tls_with_config(request, None, false, Some(connector))
.await
.map_err(|e| LqpError::WebSocketError(e.to_string()))?;
info!("WebSocket connected, subscribing to events");
@@ -306,9 +303,7 @@ impl LqpClient {
match msg {
Ok(Message::Text(text)) => {
debug!("Received text message: {} bytes", text.len());
if text.is_empty() {
debug!("Empty text message received, skipping");
continue;
}
if let Some(event) = Self::parse_websocket_message(&text) {
@@ -370,8 +365,6 @@ impl LqpClient {
/// Parse a WebSocket message into a game event.
fn parse_websocket_message(text: &str) -> Option<GameEvent> {
debug!("WebSocket message: {}", text);
// Parse the message array format: [type, callback, data]
let value: serde_json::Value = match serde_json::from_str(text) {
Ok(v) => v,
@@ -383,24 +376,23 @@ impl LqpClient {
// Check if it's an event message (type 8)
if let Some(arr) = value.as_array() {
debug!("Message is array with {} elements", arr.len());
if arr.len() >= 3 {
let msg_type = arr.first()?.as_u64()?;
debug!("Message type: {}", msg_type);
if msg_type == 8 {
// Event message format: [8, "OnJsonApiEvent", {"data": ..., "eventType": ..., "uri": ...}]
let callback = arr.get(1)?.as_str()?;
let event_data = arr.get(2)?;
if callback == "OnJsonApiEvent" {
// Extract the actual URI and data from the event
let uri = event_data.get("uri")?.as_str()?;
let data = event_data.get("data")?;
let event_type = event_data.get("eventType").and_then(|t| t.as_str()).unwrap_or("Update");
debug!("OnJsonApiEvent: uri={}, eventType={}, data={:?}", uri, event_type, data);
let event_type = event_data
.get("eventType")
.and_then(|t| t.as_str())
.unwrap_or("Update");
return Self::parse_event_from_uri(uri, event_type, data);
} else {
debug!("Unknown callback: {}", callback);
@@ -411,6 +403,8 @@ impl LqpClient {
} else if msg_type == 0 {
// Welcome message
info!("WebSocket welcome message received");
} else {
debug!("Unknown message type {msg_type} received");
}
}
} else {
@@ -421,14 +415,18 @@ impl LqpClient {
}
/// Parse an event based on the URI.
fn parse_event_from_uri(uri: &str, event_type: &str, data: &serde_json::Value) -> Option<GameEvent> {
fn parse_event_from_uri(
uri: &str,
event_type: &str,
data: &serde_json::Value,
) -> Option<GameEvent> {
info!("Parsing event from URI: {} (type: {})", uri, event_type);
// Handle gameflow phase changes
if uri == "/lol-gameflow/v1/gameflow-phase" {
let phase = data.as_str()?;
info!("Gameflow phase changed to: {}", phase);
// Update internal state based on phase
return Some(
GameEvent::from_json(&serde_json::json!({
@@ -438,22 +436,23 @@ impl LqpClient {
.unwrap_or(GameEvent::Unknown),
);
}
// Handle gameflow session updates
if uri == "/lol-gameflow/v1/session" {
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" {
info!("Game is now in progress!");
// Extract game info
let game_id = data.get("gameData")
let game_id = data
.get("gameData")
.and_then(|gd| gd.get("gameId"))
.and_then(|id| id.as_u64())
.unwrap_or(0);
return Some(
GameEvent::from_json(&serde_json::json!({
"eventType": "lcu-game-start",
@@ -462,7 +461,7 @@ impl LqpClient {
.unwrap_or(GameEvent::Unknown),
);
}
return Some(
GameEvent::from_json(&serde_json::json!({
"eventType": "lcu-phase-change",
@@ -472,31 +471,31 @@ impl LqpClient {
);
}
}
// Handle game events (kills, deaths, objectives)
if uri == "/lol-game-events/v1/game-events" {
info!("Game event received: {:?}", data);
return GameEvent::from_json(data);
}
// Handle ready check
if uri == "/lol-matchmaking/v1/ready-check" {
info!("Ready check event: {:?}", data);
return None;
}
// Handle champion select
if uri == "/lol-champ-select/v1/session" {
info!("Champion select event: {:?}", data);
return None;
}
// Handle lobby
if uri.starts_with("/lol-lobby") {
debug!("Lobby event: {}", uri);
return None;
}
debug!("Unhandled URI: {}", uri);
None
}